home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Common / src / didcfgview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  113.6 KB  |  3,850 lines

  1. //-----------------------------------------------------------------------------
  2. // File: didcfgview.cpp
  3. //
  4. // Desc: Interface for retrieving and rendering DirectInput Device
  5. //       configuration view( implemenation ). Feel free to use 
  6. //       this class as a starting point for adding extra functionality.
  7. //
  8. //
  9. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  10. //-----------------------------------------------------------------------------
  11. #include <d3d8.h>
  12. #include <d3dx8tex.h>
  13. #include <assert.h>
  14. #include <tchar.h>
  15. #include "didcfgview.h"
  16. #include "dxutil.h"
  17.  
  18.  
  19.  
  20.  
  21. //-----------------------------------------------------------------------------
  22. // Name: DIDCfgView()
  23. // Desc: constructor
  24. //-----------------------------------------------------------------------------
  25. DIDCfgView::DIDCfgView()
  26.     :   m_lpViewManager( NULL ),
  27.         m_lpCalloutManager( NULL ),
  28.         m_bIsInit( FALSE ),
  29.         m_nView( DIDCV_INVALID_ID ),
  30.         m_lpDidImgHeader( NULL ),
  31.         m_lpCustomViewInfo( NULL ),
  32.         m_lpDIDevice( NULL ),
  33.         m_bCanBeCollapsed( FALSE ),
  34.         m_bIsCollapsed( FALSE ),
  35.         m_lpDiaf( NULL ),
  36.         m_crFore( RGB( 0xff, 0xff, 0xff ) ),
  37.         m_crBack( RGB( 0x0, 0x0, 0x0 ) ),
  38.         m_crHighlight( RGB( 0x33, 0x33, 0x33 ) ),
  39.         m_crHighlightLine( RGB( 0x99, 0xff, 0x0 ) ),
  40.         m_hFont( NULL )
  41. {
  42.     _tcscpy( m_tszDefaultText, TEXT( "- - -" ) );
  43.     ZeroMemory( &m_ptOrigin, sizeof( POINT ) );
  44. }
  45.  
  46.  
  47.  
  48.  
  49. //-----------------------------------------------------------------------------
  50. // Name: ~DIDCfgView()
  51. // Desc: destructor
  52. //-----------------------------------------------------------------------------
  53. DIDCfgView::~DIDCfgView()
  54. {
  55.     CleanUp();
  56.     
  57.     if( m_hFont )
  58.     {
  59.         // free the font
  60.         DeleteObject( m_hFont );
  61.         m_hFont = NULL;
  62.     }
  63. }
  64.  
  65.  
  66.  
  67.  
  68. //-----------------------------------------------------------------------------
  69. // Name: Init()
  70. // Desc: initializes the DIDCfgView object with a DirectInputDevice8
  71. //       reference.  upon successful completion of this functions, image
  72. //       and callout data for the device should be successfully retrieved,
  73. //       loaded, and processed, ready to be used.( ultimately, after optionally 
  74. //       setting the action format, callout state, performing hit tests, etc -
  75. //       the image can be drawn by calling RenderView(). )  this Init()
  76. //       must be called successfully before anything else can be used.
  77. //-----------------------------------------------------------------------------
  78. HRESULT DIDCfgView::Init( LPDIRECTINPUTDEVICE8 lpDidev )
  79. {
  80.     HRESULT hr;
  81.  
  82.     // always start clean
  83.     CleanUp();
  84.  
  85.     // sanity check
  86.     if( NULL == lpDidev )
  87.     {
  88.         return DIERR_INVALIDPARAM;
  89.     }
  90.  
  91.     // allocate objects
  92.     hr = InitAlloc();
  93.     if( FAILED( hr ) )
  94.     {
  95.         CleanUp();
  96.         return hr;
  97.     }
  98.  
  99.     // retrieve the image info from DirectInput
  100.     hr = InitImageInfoRetrieve( lpDidev );
  101.     if( FAILED( hr ) )
  102.     {
  103.         // no device image on system, let's build our own
  104.         hr = InitCustomViews( lpDidev );
  105.         if( FAILED( hr ) )
  106.         {
  107.             CleanUp();
  108.             return hr;
  109.         }
  110.  
  111.         // keep a reference for custom views, since we might
  112.         // need the device to reconstruct collapsed views
  113.         m_lpDIDevice = lpDidev;
  114.         m_lpDIDevice->AddRef();
  115.     }
  116.     else
  117.     {
  118.         // process the image info from DirectInput
  119.         hr = InitImageInfoProcess();
  120.         if( FAILED( hr ) )
  121.         {
  122.             CleanUp();
  123.             return hr;
  124.         }
  125.     }
  126.  
  127.     m_bIsInit = TRUE;
  128.     return S_OK;
  129. }
  130.  
  131.  
  132.  
  133.  
  134. //-----------------------------------------------------------------------------
  135. // Name: CleanUp()
  136. // Desc: resets the cfgview object, freeing memory and other resources
  137. //       this method is idempotent.
  138. //-----------------------------------------------------------------------------
  139. VOID DIDCfgView::CleanUp()
  140. {
  141.     m_bIsInit = FALSE;
  142.     m_nView = -1;
  143.     m_bCanBeCollapsed = FALSE;
  144.     m_bIsCollapsed = FALSE;
  145.     
  146.     if( m_lpDidImgHeader )
  147.     {
  148.         // free array
  149.         SAFE_DELETE_ARRAY( m_lpDidImgHeader->lprgImageInfoArray );
  150.  
  151.         // free the imginfoheader
  152.         delete m_lpDidImgHeader;
  153.         m_lpDidImgHeader = NULL;
  154.     }
  155.  
  156.     // free the view manager
  157.     SAFE_DELETE( m_lpViewManager );
  158.  
  159.     // free callout manager
  160.     SAFE_DELETE( m_lpCalloutManager );
  161.  
  162.     // free the custom view info
  163.     SAFE_DELETE( m_lpCustomViewInfo );
  164.  
  165.     // release the DirectInputDevice
  166.     SAFE_RELEASE( m_lpDIDevice );
  167.  
  168.     if( m_lpDiaf )
  169.     {
  170.         // free the DIACTION array
  171.         SAFE_DELETE_ARRAY( m_lpDiaf->rgoAction );
  172.  
  173.         // free the DIACTIONFORMAT
  174.         delete m_lpDiaf;
  175.         m_lpDiaf = NULL;
  176.     }
  177. }
  178.  
  179.  
  180.  
  181.  
  182. //-----------------------------------------------------------------------------
  183. // Name: SetActionFormat()
  184. // Desc: sets the action format mapping for this cfgview object.  the action
  185. //       format should be relevant to the same DirectInputDevice that was
  186. //       used to initialize this object.  this information will be used when
  187. //       the configuration view is rendered.
  188. //-----------------------------------------------------------------------------
  189. HRESULT DIDCfgView::SetActionFormat( LPDIACTIONFORMAT lpDiaf )
  190. {
  191.     UINT i;
  192.  
  193.     // make sure this object has been properly initialized
  194.     if( FALSE == m_bIsInit )
  195.         return DIERR_NOTINITIALIZED;
  196.  
  197.     // clear any actions currently mapped
  198.     m_lpCalloutManager->ClearAllActionMaps();
  199.  
  200.     // no DIACTIONFORMAT passed in, error
  201.     if( NULL == lpDiaf )
  202.         return DIERR_INVALIDPARAM;
  203.  
  204.     // set each action mapping
  205.     for( i = 0; i < lpDiaf->dwNumActions; i++ )
  206.     {
  207.         m_lpCalloutManager->SetActionMap( &( lpDiaf->rgoAction[i] ), 
  208.                                           lpDiaf->rgoAction[i].dwObjID );
  209.     }
  210.  
  211.     // if we build custom views
  212.     if( m_lpCustomViewInfo )
  213.     {
  214.         // determine if views can be compacted
  215.         m_bCanBeCollapsed = m_lpCalloutManager->CalcCanBeCollapsed();
  216.  
  217.         // keep copy of the action map
  218.         if( m_bCanBeCollapsed )
  219.             if( FALSE == CopyActionMap( lpDiaf ) )
  220.                 return DIERR_OUTOFMEMORY;
  221.     }
  222.  
  223.     return S_OK;
  224. }
  225.  
  226.  
  227.  
  228.  
  229. //-----------------------------------------------------------------------------
  230. // Name: RebuildViews()
  231. // Desc: collapses or exands the views
  232. //-----------------------------------------------------------------------------
  233. HRESULT DIDCfgView::RebuildViews( BOOL bCompact )
  234. {
  235.     UINT i;
  236.     INT  iNumViews;
  237.  
  238.     // make sure this has been properly initialized
  239.     if( FALSE == m_bIsInit )
  240.         return DIERR_NOTINITIALIZED;
  241.  
  242.     if( NULL == m_lpDiaf )
  243.         return DIERR_NOTINITIALIZED;
  244.  
  245.     if( FALSE == m_bCanBeCollapsed )
  246.         return DIERR_INVALIDPARAM;
  247.  
  248.     // build the custom views, expand or compact
  249.     InitCustomViews( m_lpDIDevice, bCompact );
  250.  
  251.     // set the action map
  252.     for( i = 0; i < m_lpDiaf->dwNumActions; i++ )
  253.     {
  254.         m_lpCalloutManager->SetActionMap( &( m_lpDiaf->rgoAction[i] ), 
  255.                                           m_lpDiaf->rgoAction[i].dwObjID );
  256.     }
  257.  
  258.     // get the new number of views;
  259.     iNumViews = m_lpViewManager->GetNumViews();
  260.  
  261.     // bound the current view id
  262.     if( iNumViews == 0 )
  263.         m_nView = DIDCV_INVALID_ID;
  264.  
  265.     if( m_nView >= iNumViews )
  266.         m_nView  = iNumViews - 1;
  267.  
  268.     // keep track of whether the views are compact or not
  269.     m_bIsCollapsed = bCompact;
  270.  
  271.     return S_OK;
  272. }
  273.  
  274.  
  275.  
  276.  
  277. //-----------------------------------------------------------------------------
  278. // Name: SetCalloutState()
  279. // Desc: sets the state for a given callout.  the flags are:
  280. //
  281. //       DIDCV_DRAWCALLOUT - draws the callout
  282. //       DIDCV_DRAWOVERLAY - draws the overlay
  283. //       DIDCV_DRAWHIGHLIGHT - draws highlight
  284. //       DIDCV_DRAWEMPTYCALLOUT - draws the callout even if an action mapping
  285. //          is not present
  286. //       DIDCV_DRAWFULLNAME - draws the full name of action, if the
  287. //          callout clips part of the string
  288. //
  289. //       the dwFlags argument should be a bitwise AND of none, any, or all of
  290. //       the values.
  291. //-----------------------------------------------------------------------------
  292. HRESULT DIDCfgView::SetCalloutState( DWORD dwFlags, DWORD dwObjID )
  293. {
  294.     DidcvCalloutState calloutState;
  295.     BOOL bResult;
  296.     
  297.     // make sure this object has been properly initialized
  298.     if( FALSE == m_bIsInit )
  299.         return DIERR_NOTINITIALIZED;
  300.  
  301.     // set the state structure to match the dword
  302.     calloutState.SetFlag( dwFlags );
  303.  
  304.     // set the state for the object id( if exist )
  305.     bResult = m_lpCalloutManager->SetCalloutState( &calloutState, dwObjID );
  306.  
  307.     // could be an invalid object id
  308.     if( FALSE == bResult )
  309.         return DIERR_INVALIDPARAM;
  310.  
  311.     return DI_OK;
  312. }
  313.  
  314.  
  315.  
  316.  
  317. //-----------------------------------------------------------------------------
  318. // Name: SetAllCalloutState()
  319. // Desc: sets the state for all callouts.  see SetCalloutState for flag value
  320. //-----------------------------------------------------------------------------
  321. HRESULT DIDCfgView::SetAllCalloutState( DWORD dwFlags )
  322. {
  323.     DidcvCalloutState calloutState;
  324.     BOOL bResult;
  325.     
  326.     // make sure this object has been properly initialized
  327.     if( FALSE == m_bIsInit )
  328.         return DIERR_NOTINITIALIZED;
  329.  
  330.     // set the state structure to match the dword
  331.     calloutState.SetFlag( dwFlags );
  332.  
  333.     // set the state for the object id( if exist )
  334.     bResult = m_lpCalloutManager->SetAllCalloutState( &calloutState );
  335.  
  336.     // could be an invalid object id
  337.     if( FALSE == bResult )
  338.         return DIERR_INVALIDPARAM;
  339.  
  340.     return DI_OK;
  341. }
  342.  
  343.  
  344.  
  345.  
  346. //-----------------------------------------------------------------------------
  347. // Name: GetCalloutState()
  348. // Desc: returns the state for a given callout.  see SetCalloutState comments
  349. //       for explanation of the flags values
  350. //-----------------------------------------------------------------------------
  351. HRESULT DIDCfgView::GetCalloutState( LPDWORD lpdwFlags, DWORD dwObjID )
  352. {
  353.     DidcvCalloutState calloutState;
  354.     BOOL bResult;
  355.  
  356.     // make sure this object has been properly initialized
  357.     if( FALSE == m_bIsInit )
  358.         return DIERR_NOTINITIALIZED;
  359.  
  360.     // sanity check
  361.     if( NULL == lpdwFlags )
  362.         return DIERR_INVALIDPARAM;
  363.  
  364.     // retrieve callout state from the callout manager
  365.     bResult = m_lpCalloutManager->GetCalloutState( &calloutState, dwObjID );
  366.  
  367.     // did not find state info
  368.     if( FALSE == bResult )
  369.         return DIERR_INVALIDPARAM;
  370.  
  371.     // construct flag from the state
  372.     *lpdwFlags = calloutState.MakeFlag();
  373.  
  374.     return DI_OK;
  375. }
  376.  
  377.  
  378.  
  379.  
  380. //-----------------------------------------------------------------------------
  381. // Name: GetObjectIDByLocation()
  382. // Desc: for a given point in image coordinate, returns a callout with which
  383. //       the point intersects.  if not found, the functions return success,
  384. //       and the return argument will be set to NULL.
  385. //-----------------------------------------------------------------------------
  386. HRESULT DIDCfgView::GetObjectIDByLocation( LPDWORD lpdwObjID, LPPOINT pPt )
  387. {
  388.     POINT ptTransform;
  389.  
  390.     // make sure this object has been properly initialized
  391.     if( FALSE == m_bIsInit )
  392.         return DIERR_NOTINITIALIZED;
  393.  
  394.     // sanity check
  395.     if( NULL == lpdwObjID )
  396.         return DIERR_INVALIDPARAM;
  397.  
  398.     // transform by new origin
  399.     ptTransform.x = pPt->x - m_ptOrigin.x;
  400.     ptTransform.y = pPt->y - m_ptOrigin.y;
  401.  
  402.     // pass pt into the callout manager with the current view for hit test
  403.     *lpdwObjID = m_lpCalloutManager->GetObjectIDByLocation( &ptTransform, m_nView );
  404.  
  405.     return DI_OK;
  406. }
  407.  
  408.  
  409.  
  410.  
  411. //-----------------------------------------------------------------------------
  412. // Name: SetCurrentView()
  413. // Desc: set the current view for the DIDCfgView object.  all further
  414. //       operations will be done in the context of this new view.
  415. //-----------------------------------------------------------------------------
  416. HRESULT DIDCfgView::SetCurrentView( INT nView )
  417. {
  418.     // make sure this object has been properly initialized
  419.     if( FALSE == m_bIsInit )
  420.         return DIERR_NOTINITIALIZED;
  421.  
  422.     // sanity check
  423.     if( nView < 0 || nView >=( INT ) m_lpViewManager->GetNumViews() )
  424.         return DIERR_INVALIDPARAM;
  425.  
  426.     // set the view
  427.     m_nView = nView;
  428.  
  429.     return DI_OK;
  430. }
  431.  
  432.  
  433.  
  434.  
  435. //-----------------------------------------------------------------------------
  436. // Name: GetCurrentView()
  437. // Desc: returns the current view identifier
  438. //-----------------------------------------------------------------------------
  439. HRESULT DIDCfgView::GetCurrentView( LPINT lpnView  )
  440. {
  441.     // make sure this object has been properly initialized
  442.     if( FALSE == m_bIsInit )
  443.         return DIERR_NOTINITIALIZED;
  444.  
  445.     // sanity check
  446.     if( NULL == lpnView )
  447.         return DIERR_INVALIDPARAM;
  448.  
  449.     // copy the view
  450.     *lpnView = m_nView;
  451.  
  452.     return DI_OK;
  453. }
  454.  
  455.  
  456.  
  457.  
  458. //-----------------------------------------------------------------------------
  459. // Name: GetInfo()
  460. // Desc: retrieves information from DIDCfgView
  461. //-----------------------------------------------------------------------------
  462. HRESULT DIDCfgView::GetInfo( DIDCfgViewInfo* pCfgViewInfo )
  463. {
  464.     // sanity checks
  465.     if( NULL == pCfgViewInfo )
  466.         return DIERR_INVALIDPARAM;
  467.  
  468.     ZeroMemory( pCfgViewInfo, sizeof( DIDCfgViewInfo ) );
  469.  
  470.     // always return whether the Config Viewer is initialized or not
  471.     pCfgViewInfo->bIsInit = m_bIsInit;
  472.  
  473.     // make sure this object has been properly initialized
  474.     if( FALSE == m_bIsInit )
  475.         return DIERR_NOTINITIALIZED;
  476.  
  477.     // set the information to be returned
  478.     pCfgViewInfo->iCurrentViewID = m_nView;
  479.     pCfgViewInfo->iNumTotalViews =( INT )m_lpViewManager->GetNumViews();
  480.     pCfgViewInfo->dwNumUniqueCallouts = m_lpCalloutManager->GetNumUniqueCallouts();
  481.     pCfgViewInfo->bCanBeCollapsed = m_bCanBeCollapsed;
  482.     pCfgViewInfo->bIsCollapsed = m_bIsCollapsed;
  483.  
  484.     return DI_OK;
  485. }
  486.  
  487.  
  488.  
  489.  
  490. //-----------------------------------------------------------------------------
  491. // Name: SetColors()
  492. // Desc: sets the foreground( text ) color, background and highlight color,
  493. //       the highlighted callout color
  494. //-----------------------------------------------------------------------------
  495. VOID DIDCfgView::SetColors( COLORREF crFore, COLORREF crBack, 
  496.                             COLORREF crHighlight, COLORREF crHighlightLine )
  497. {
  498.     m_crFore = crFore;
  499.     m_crBack = crBack;
  500.     m_crHighlight = crHighlight;
  501.     m_crHighlightLine = crHighlightLine;
  502. }
  503.  
  504.  
  505.  
  506.  
  507. //-----------------------------------------------------------------------------
  508. // Name: GetColor()
  509. // Desc: returns the colors currently being using in rendering
  510. //-----------------------------------------------------------------------------
  511. VOID DIDCfgView::GetColors( COLORREF* pCrFore, COLORREF* pCrBack, 
  512.                             COLORREF* pCrHighlight, COLORREF* pCrHighlightLine )
  513. {
  514.     if( pCrFore ) *pCrFore = m_crFore;
  515.     if( pCrBack ) *pCrBack = m_crBack;
  516.     if( pCrHighlight ) *pCrHighlight = m_crHighlight;
  517.     if( pCrHighlightLine ) *pCrHighlightLine = m_crHighlightLine;
  518. }
  519.  
  520.  
  521.  
  522.  
  523. //-----------------------------------------------------------------------------
  524. // Name: SetFont()
  525. // Desc: sets the font used to draw the text
  526. //-----------------------------------------------------------------------------
  527. HRESULT DIDCfgView::SetFont( const TCHAR* pctszFontName, DWORD dwAttribs )
  528. {
  529.     HDC hDCMem;
  530.     HFONT hFont;
  531.     HRESULT hr = DI_OK;
  532.  
  533.     if( NULL == pctszFontName )
  534.     {
  535.         if( m_hFont )
  536.             DeleteObject( m_hFont );
  537.     }
  538.     else
  539.     {
  540.         // create a memory device context
  541.         hDCMem = CreateCompatibleDC( NULL );
  542.  
  543.         // create font
  544.         hFont = DidcvCreateFont( hDCMem, pctszFontName, DIDCV_DEFAULT_FONT_SIZE, 
  545.                                  0, dwAttribs, FALSE );
  546.  
  547.         if( NULL == hFont )
  548.             hr = DIERR_INVALIDPARAM;
  549.         else
  550.         {
  551.             if( m_hFont )
  552.                 DeleteObject( m_hFont );
  553.  
  554.             m_hFont = hFont;
  555.         }
  556.  
  557.         // clean up
  558.         DeleteDC( hDCMem );
  559.     }
  560.  
  561.     return hr;
  562. }
  563.  
  564.  
  565.  
  566.  
  567. //-----------------------------------------------------------------------------
  568. // Name: GetFont()
  569. // Desc: sets the font used to draw the text
  570. //-----------------------------------------------------------------------------
  571. HFONT   DIDCfgView::GetFont()
  572. {
  573.     return m_hFont;
  574. }
  575.  
  576.  
  577.  
  578.  
  579. //-----------------------------------------------------------------------------
  580. // Name: SetViewOrigin
  581. // Desc: tells DIDCfgView where to start drawing and performing hit tests
  582. //       on the surface being rendered on
  583. //-----------------------------------------------------------------------------
  584. HRESULT DIDCfgView::SetViewOrigin( const POINT* pPtOrg, POINT* pPtOldOrg )
  585. {
  586.     if( NULL == pPtOrg )
  587.         return DIERR_INVALIDPARAM;
  588.  
  589.     // return the current origin
  590.     if( pPtOldOrg )
  591.     {
  592.         pPtOldOrg->x = m_ptOrigin.x;
  593.         pPtOldOrg->y = m_ptOrigin.y;
  594.     }
  595.  
  596.     // set the current origin to new origin
  597.     m_ptOrigin.x = pPtOrg->x;
  598.     m_ptOrigin.y = pPtOrg->y;
  599.  
  600.     return DI_OK;
  601. }
  602.  
  603.  
  604.  
  605.  
  606. //-----------------------------------------------------------------------------
  607. // Name: CalcCenterOrgForCurrentView()
  608. // Desc: calculate the coordinate where to set the origin, in order for the
  609. //       current view to be centered on the drawing surface, lpImgSize should
  610. //       contain the dimensions of the drawing surface.  if the view is
  611. //       larger than the drawing area, then( 0, 0 ) will be returned
  612. //-----------------------------------------------------------------------------
  613. HRESULT DIDCfgView::CalcCenterOrgForCurrentView( const SIZE* pSurfaceSize, 
  614.                                                  POINT* pCenterOrg, BOOL bSetOrigin )
  615. {
  616.     if( FALSE == m_bIsInit )
  617.         return DIERR_NOTINITIALIZED;
  618.  
  619.     // sanity check
  620.     if( NULL == pSurfaceSize || NULL == pCenterOrg )
  621.         return DIERR_INVALIDPARAM;
  622.  
  623.     INT x = 0, y = 0;
  624.     DidcvView* pView;
  625.     SIZE imgSize;
  626.  
  627.     // get the current view
  628.     pView = m_lpViewManager->GetImage( m_nView );
  629.  
  630.     // get the size and find the coordinate at which to center the image
  631.     // note that x == 0 and y == 0 if surface width and height
  632.     // is not as big as the image width and height, respectively
  633.     if( pView && pView->GetViewSize( &imgSize ) )
  634.     {
  635.         if( imgSize.cx < pSurfaceSize->cx )
  636.             x =( pSurfaceSize->cx - imgSize.cx ) / 2;
  637.         if( imgSize.cy < pSurfaceSize->cy )
  638.             y =( pSurfaceSize->cy - imgSize.cy ) / 2;
  639.     }
  640.  
  641.     // set the values to be returns
  642.     pCenterOrg->x = x;
  643.     pCenterOrg->y = y;
  644.  
  645.     // if bSetOrigin is TRUE, then set the view origin for this object
  646.     if( bSetOrigin )
  647.         SetViewOrigin( pCenterOrg, NULL );
  648.  
  649.     return S_OK;
  650. }
  651.  
  652.  
  653.  
  654.  
  655. //-----------------------------------------------------------------------------
  656. // Name: SetDefaultText()
  657. // Desc: sets the default text for callouts that doesn't have action mapped
  658. //-----------------------------------------------------------------------------
  659. VOID DIDCfgView::SetDefaultText( const TCHAR* pctszDefaultText, DWORD length )
  660. {
  661.     // copy up to MAX_PATH characters
  662.     size_t numToCopy =( length < MAX_PATH ? length : MAX_PATH );
  663.     _tcsncpy( m_tszDefaultText, pctszDefaultText, numToCopy );
  664.  
  665.     // if we copied MAX_PATH, make sure it is NULL terminated
  666.     if( numToCopy == MAX_PATH )
  667.         m_tszDefaultText [MAX_PATH - 1] = 0;
  668. }
  669.  
  670.  
  671.  
  672.  
  673. //-----------------------------------------------------------------------------
  674. // Name: RenderView()
  675. // Desc: draws the configuration view to HBITMAP, a DDB or a DIB
  676. //-----------------------------------------------------------------------------
  677. HRESULT DIDCfgView::RenderView( HBITMAP hBitmap, BOOL bIsDib )
  678. {
  679.     HDC hDCMem;
  680.     HGDIOBJ hOldBitmap;
  681.     DIBSECTION dibs;
  682.     HRESULT hr;
  683.  
  684.     // make sure this object has been properly initialized
  685.     if( FALSE == m_bIsInit )
  686.         return DIERR_NOTINITIALIZED;
  687.  
  688.     // sanity check
  689.     if( NULL == hBitmap )
  690.         return DIERR_INVALIDPARAM;
  691.  
  692.     // create a memory DC compatible with the current display
  693.     hDCMem = CreateCompatibleDC( NULL );
  694.     // select the surface to drawn on into the HDC
  695.     hOldBitmap = SelectObject( hDCMem, hBitmap );
  696.  
  697.     // render, passing in as much data as we can safely acquire
  698.     if( bIsDib && GetObject( hBitmap, sizeof( DIBSECTION ), &dibs ) )
  699.         hr = RenderView( hDCMem, dibs.dsBm.bmBits, dibs.dsBm.bmWidth, dibs.dsBm.bmHeight );
  700.     else
  701.         hr = RenderView( hDCMem );
  702.  
  703.     // clean up
  704.     SelectObject( hDCMem, hOldBitmap );
  705.     DeleteDC( hDCMem );
  706.  
  707.     return hr;
  708. }
  709.  
  710.  
  711.  
  712.  
  713. //-----------------------------------------------------------------------------
  714. // Name: RenderView()
  715. // Desc: draws the configuration view to an HDC
  716. //-----------------------------------------------------------------------------
  717. HRESULT DIDCfgView::RenderView( HDC hdc )
  718. {
  719.     return RenderView( hdc, NULL, 0, 0 );
  720. }
  721.  
  722.  
  723.  
  724.  
  725. //-----------------------------------------------------------------------------
  726. // Name: RenderView()
  727. // Desc: draws the configuration view to an HDC
  728. //-----------------------------------------------------------------------------
  729. HRESULT DIDCfgView::RenderView( HDC hdc, VOID* pBits, INT width, INT height )
  730. {
  731.     DidcvView* pView;
  732.     const DidcvCalloutSet* pSet;
  733.     int iDCStackNum;
  734.     
  735.     // make sure this object has been properly initialized
  736.     if( FALSE == m_bIsInit )
  737.         return DIERR_NOTINITIALIZED;
  738.  
  739.     if( NULL == hdc )
  740.         return DIERR_INVALIDPARAM;
  741.  
  742.     pView = m_lpViewManager->GetImage( m_nView );
  743.     
  744.     // no valid view set
  745.     if( NULL == pView )
  746.         return DIERR_NOTINITIALIZED;
  747.  
  748.  
  749.     // set rendering options for HDC
  750.     HBRUSH hBkBrush = CreateSolidBrush( m_crHighlight );
  751.     HPEN hLinePen = CreatePen( PS_SOLID, 0, m_crFore );
  752.     HPEN hHighlightPen = CreatePen( PS_SOLID, 0, m_crHighlight );
  753.     HPEN hHighlightLinePen = CreatePen( PS_SOLID, 0, m_crHighlightLine );
  754.  
  755.     // save the state of the DC on the context stack
  756.     iDCStackNum = SaveDC( hdc );
  757.  
  758.     // select the new highlight background color brush
  759.     SelectObject( hdc, hBkBrush );
  760.     // select the callout line color
  761.     SelectObject( hdc, hLinePen );
  762.     // set text color
  763.     SetTextColor( hdc, m_crFore );
  764.     // set background color
  765.     SetBkColor( hdc, m_crBack );
  766.     // shift the origin
  767.     SetViewportOrgEx( hdc, m_ptOrigin.x, m_ptOrigin.y, NULL );
  768.     // the bk mode for drawing text
  769.     SetBkMode( hdc, TRANSPARENT );
  770.  
  771.     // draw the current view
  772.     pView->Render( hdc, pBits, width, height, &m_ptOrigin );
  773.  
  774.     // get the set of callouts associated with the current view
  775.     pSet = m_lpCalloutManager->GetCalloutSetByView( m_nView );
  776.  
  777.     if( pSet )
  778.     {
  779.         // Get the list of callout in the set.
  780.         // A callout is the line drawn from each axis/button to a label
  781.         const GwArray <DidcvCallout *> & arr = pSet->GetInternalArrayRef();
  782.         const DidcvCalloutData* pData;
  783.  
  784.         UINT i;
  785.         BOOL bCalloutEmpty;
  786.         DWORD dwNumPts = 0;
  787.         const POINT* lpPts;
  788.         TCHAR szBuffer[MAX_PATH];
  789.         TCHAR szCopy[MAX_PATH];
  790.         DidcvActionMap* lpActionMap;
  791.         DWORD dwTextFlags, dwTextAlign;
  792.  
  793.         if( m_hFont )
  794.         {
  795.             // set the font
  796.             SelectObject( hdc, m_hFont );
  797.         }
  798.  
  799.         // for each callout (the line drawn from each axis/button to a label)
  800.         for( i = 0; i < arr.Size(); i++ )
  801.         {
  802.             // the data associated
  803.             pData = arr[i]->GetDataRef();
  804.             const RECT* rect = &( arr[i]->GetCalloutRect() );
  805.  
  806.             // get the action map, if one exists
  807.             lpActionMap = pData->lpActionMap;
  808.             if( lpActionMap && lpActionMap->dia.lptszActionName )
  809.                 bCalloutEmpty = FALSE;
  810.             else
  811.                 bCalloutEmpty = TRUE;
  812.  
  813.             // draw the callout for the control
  814.             if( !bCalloutEmpty || pData->lpState->bDrawEmptyCallout )
  815.             {
  816.                 // draw the highlight first
  817.                 if( pData->lpState->bDrawHighlight )
  818.                 {
  819.                     // draw the highlight
  820.                     SelectObject( hdc, hHighlightPen );
  821.                     Rectangle( hdc, rect->left, rect->top, rect->right, rect->bottom );
  822.  
  823.                     // set pen to highlight line
  824.                     SelectObject( hdc, hHighlightLinePen );
  825.  
  826.                     // set back ground color to highlight color
  827.                     SetBkColor( hdc, m_crHighlight );
  828.  
  829.                     // set the text color to highlightline color
  830.                     // SetTextColor( hdc, m_crHighlightLine );
  831.                 }
  832.  
  833.                 // draw the overlay image
  834.                 if( pData->lpState->bDrawOverlay )
  835.                 {
  836.                     arr[i]->DrawOverlay( hdc, pBits, width, height, &m_ptOrigin );
  837.                 }
  838.  
  839.                 // draw the callout line and text
  840.                 if( pData->lpState->bDrawCallout )
  841.                 {
  842.                     // draw the callout line
  843.                     lpPts = arr[i]->GetCalloutLine( &dwNumPts );
  844.                     DidcvPolyLineArrow( hdc, lpPts,( INT ) dwNumPts, FALSE );
  845.  
  846.                     // set the draw text options
  847.                     dwTextFlags = DT_WORDBREAK | DT_NOPREFIX | DT_END_ELLIPSIS 
  848.                                 | DT_EDITCONTROL | DT_MODIFYSTRING;
  849.  
  850.                     if( !bCalloutEmpty )
  851.                     {
  852.                         // copy the text
  853.                         _tcscpy( szBuffer, lpActionMap->dia.lptszActionName );
  854.  
  855.                         // reset the text flags
  856.                         dwTextAlign = arr[i]->GetTextAlign();
  857.  
  858.                         // check horizontal alignment
  859.                         if( dwTextAlign & DIDAL_LEFTALIGNED )
  860.                             dwTextFlags |= DT_LEFT;
  861.                         else if( dwTextAlign & DIDAL_RIGHTALIGNED )
  862.                             dwTextFlags |= DT_RIGHT;
  863.                         else //( dwTextAlign & DIDAL_CENTERED )
  864.                             dwTextFlags |= DT_CENTER;
  865.  
  866.                         // check vertical alignment
  867.                         if( dwTextAlign & DIDAL_TOPALIGNED )
  868.                             dwTextFlags |= DT_TOP;
  869.                         else if( dwTextAlign & DIDAL_BOTTOMALIGNED )
  870.                             dwTextFlags |= DT_SINGLELINE | DT_BOTTOM;
  871.                         else //( dwTextAlign & DIDAL_MIDDLE )
  872.                             dwTextFlags |= DT_SINGLELINE | DT_VCENTER;
  873.  
  874.                     }
  875.                     else
  876.                     {
  877.                         // copy and draw the default text
  878.                         _tcscpy( szBuffer, m_tszDefaultText );
  879.                         dwTextFlags |= DT_VCENTER | DT_SINGLELINE;
  880.                     }
  881.  
  882.                     // make a copy
  883.                     _tcscpy( szCopy, szBuffer );
  884.  
  885.                     // draw the text
  886.                     DrawText( hdc, szCopy, -1,( LPRECT ) rect, dwTextFlags );
  887.  
  888.                     // rendered string truncated
  889.                     if( pData->lpState->bDrawFullname && _tcscmp( szCopy, szBuffer ) )
  890.                     {
  891.                         RenderFullname( hdc, szBuffer, rect );
  892.                     }
  893.  
  894.                     if( pData->lpState->bDrawHighlight )
  895.                     {
  896.                         // reset the pen
  897.                         SelectObject( hdc, hLinePen );
  898.  
  899.                         // reset the back ground color
  900.                         SetBkColor( hdc, m_crBack );
  901.  
  902.                         // reset the text color
  903.                         // SetTextColor( hdc, m_crFore );
  904.                     }
  905.                 }
  906.             }
  907.         }
  908.     }
  909.  
  910.     // restore DC state
  911.     RestoreDC( hdc, iDCStackNum );
  912.  
  913.     // clean up
  914.     DeleteObject( hBkBrush );
  915.     DeleteObject( hLinePen );
  916.     DeleteObject( hHighlightPen );
  917.     DeleteObject( hHighlightLinePen );
  918.  
  919.     return S_OK;
  920. }
  921.  
  922.  
  923.  
  924.  
  925. //-----------------------------------------------------------------------------
  926. // Name: RenderFullname()
  927. // Desc: renders a box with the full name inside
  928. //-----------------------------------------------------------------------------
  929. VOID DIDCfgView::RenderFullname( HDC hdc, const TCHAR* pctszFullname, 
  930.                                  const RECT* pCalloutRect )
  931. {
  932.     HFONT hFont, hOldFont;
  933.     HBRUSH hBrush, hOldBrush;
  934.     COLORREF crOldTextColor;
  935.     TEXTMETRIC tm;
  936.     RECT rect;
  937.     DWORD dwTextFlags;
  938.     int len, width, height;
  939.  
  940.     // check the length
  941.     len = _tcslen( pctszFullname );
  942.     if( 0 == len )
  943.         return;
  944.  
  945.     // create the font to use in the box to display the full name
  946.     // we hard-code Courier to ensure we have a fix-width font
  947.     hFont = DidcvCreateFont( hdc, TEXT( "Courier" ), 
  948.                              DIDCV_DEFAULT_FONT_SIZE, 0, 0, FALSE );
  949.  
  950.     // use the foreground color as the background
  951.     hBrush = CreateSolidBrush( m_crFore );
  952.     // and vice versa
  953.     crOldTextColor = SetTextColor( hdc, m_crBack );
  954.  
  955.     hOldFont =( HFONT ) SelectObject( hdc, hFont );
  956.     hOldBrush =( HBRUSH ) SelectObject( hdc, hBrush );
  957.  
  958.     // get the width and height of the text
  959.     GetTextMetrics( hdc, &tm );
  960.     width = tm.tmAveCharWidth * len + 8;
  961.     height = tm.tmHeight + tm.tmExternalLeading + 4;
  962.  
  963.     // for now draw over the callout rect
  964.     rect.left = pCalloutRect->left;
  965.     rect.top = pCalloutRect->top;
  966.     rect.right = rect.left + width;
  967.     rect.bottom = pCalloutRect->bottom;
  968.  
  969.     // draw the rectangle
  970.     Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
  971.  
  972.     // draw the text
  973.     dwTextFlags = DT_NOPREFIX | DT_EDITCONTROL | DT_CENTER | 
  974.                   DT_VCENTER | DT_SINGLELINE;
  975.     DrawText( hdc, pctszFullname, -1, &rect, dwTextFlags );
  976.  
  977.     // restore HDC objects
  978.     SelectObject( hdc, hOldFont );
  979.     SelectObject( hdc, hOldBrush );
  980.     SetTextColor( hdc, crOldTextColor );
  981.  
  982.     // clean up
  983.     DeleteObject( hFont );
  984.     DeleteObject( hBrush );
  985. }
  986.  
  987.  
  988.  
  989.  
  990. //-----------------------------------------------------------------------------
  991. // Name: InitAlloc()
  992. // Desc: helper function to dynamically allocate memory for internal data
  993. //       structures.
  994. //-----------------------------------------------------------------------------
  995. HRESULT DIDCfgView::InitAlloc()
  996. {
  997.     // allocate a view manager, callout manager
  998.     m_lpViewManager = new DidcvViewManager;
  999.     m_lpCalloutManager = new DidcvCalloutManager;
  1000.  
  1001.     // ensure that memory has been allocated
  1002.     if( NULL == m_lpViewManager || NULL == m_lpCalloutManager )
  1003.     {
  1004.         CleanUp();
  1005.         return DIERR_OUTOFMEMORY;
  1006.     }
  1007.  
  1008.     return S_OK;
  1009. }
  1010.  
  1011.  
  1012.  
  1013.  
  1014. //-----------------------------------------------------------------------------
  1015. // Name: InitImageInfoRetrieve()
  1016. // Desc: helper function to retrieve callout / image data from
  1017. //       DirectInput
  1018. //-----------------------------------------------------------------------------
  1019. HRESULT DIDCfgView::InitImageInfoRetrieve( LPDIRECTINPUTDEVICE8 lpDidev )
  1020. {
  1021.     HRESULT hr;
  1022.  
  1023.     // allocate a DIDEVICEIMAGEINFOHEADER
  1024.     m_lpDidImgHeader = new DIDEVICEIMAGEINFOHEADER;
  1025.  
  1026.     // make sure memory has been allocated
  1027.     if( NULL == m_lpDidImgHeader )
  1028.     {
  1029.         return DIERR_OUTOFMEMORY;
  1030.     }
  1031.  
  1032.     // zero out the DIDEVICEIMAGEINFOHEADER
  1033.     ZeroMemory( m_lpDidImgHeader, sizeof( DIDEVICEIMAGEINFOHEADER ) );
  1034.  
  1035.     // properly initialize the structure before it can be used
  1036.     m_lpDidImgHeader->dwSize = sizeof( DIDEVICEIMAGEINFOHEADER );
  1037.     m_lpDidImgHeader->dwSizeImageInfo = sizeof( DIDEVICEIMAGEINFO );
  1038.  
  1039.     // since m_lpDidImgHeader->dwBufferSize is 0, this call serves to determine
  1040.     // the minimum buffer size required to hold information for all the images
  1041.     hr = lpDidev->GetImageInfo( m_lpDidImgHeader );
  1042.     if( FAILED( hr ) )
  1043.     {
  1044.         return DIERR_INVALIDPARAM; 
  1045.     }
  1046.  
  1047.     // at this point, m_lpDidImgHeader->dwBufferUsed has been set by
  1048.     // the GetImageInfo method to minimum buffer size needed, so allocate.
  1049.     m_lpDidImgHeader->dwBufferSize = m_lpDidImgHeader->dwBufferUsed;
  1050.     m_lpDidImgHeader->lprgImageInfoArray = new DIDEVICEIMAGEINFO[ m_lpDidImgHeader->dwBufferSize / 
  1051.                                                                   sizeof( DIDEVICEIMAGEINFO ) ];
  1052.  
  1053.     // make sure memory has been allocated
  1054.     if( m_lpDidImgHeader->lprgImageInfoArray == NULL )
  1055.     {
  1056.         return DIERR_OUTOFMEMORY;
  1057.     }
  1058.  
  1059.     // now that the dwBufferSize has been filled, and lprgImageArray allocated,
  1060.     // we call GetImageInfo again to get the image data
  1061.     hr = lpDidev->GetImageInfo( m_lpDidImgHeader );
  1062.     if( FAILED( hr ) )
  1063.     {
  1064.         return DIERR_INVALIDPARAM;
  1065.     }
  1066.  
  1067.     return S_OK;
  1068. }
  1069.  
  1070.  
  1071.  
  1072.  
  1073. //-----------------------------------------------------------------------------
  1074. // Name: InitImageInfoProcess()
  1075. // Desc: helper function to process the image/callout information to
  1076. //       get them ready to be used.
  1077. //-----------------------------------------------------------------------------
  1078. HRESULT DIDCfgView::InitImageInfoProcess()
  1079. {
  1080.     DWORD num_elements, i;
  1081.     DidcvView* pView = NULL;
  1082.     BOOL bLoadComplete = TRUE;
  1083.     DidcvCallout* pCallout = NULL;
  1084.     DWORD dwNumViews, dwNumCallouts, dwNumUniqueObjIDs;
  1085.  
  1086.     // a pre-condition of this method is that m_lpDidImgHeader != NULL
  1087.     assert( m_lpDidImgHeader != NULL );
  1088.  
  1089.     // calcuate the number of elements in the image info array
  1090.     num_elements = m_lpDidImgHeader->dwBufferUsed / m_lpDidImgHeader->dwSizeImageInfo;
  1091.  
  1092.     // determines sizes ahead of time
  1093.     CalcSizes( m_lpDidImgHeader->lprgImageInfoArray, num_elements, &dwNumViews, 
  1094.                &dwNumCallouts, &dwNumUniqueObjIDs );
  1095.  
  1096.     // set the capacity of the managers ahead of time
  1097.     m_lpViewManager->SetCapacity( dwNumViews );
  1098.     m_lpCalloutManager->SetCapacity( dwNumCallouts, dwNumUniqueObjIDs, dwNumViews );
  1099.  
  1100.     // first pass to process all configuration image, in order
  1101.     for( i = 0; i < num_elements; i++ )
  1102.     {
  1103.         // check to see if the element is a configuration image
  1104.         if( m_lpDidImgHeader->lprgImageInfoArray[i].dwFlags & DIDIFT_CONFIGURATION )
  1105.         {
  1106.             pView = DidcvBitmapView::Create( m_lpDidImgHeader->lprgImageInfoArray[i].tszImagePath,
  1107.                                              m_lpDidImgHeader->lprgImageInfoArray[i].dwFlags );
  1108.  
  1109.             if( NULL == pView )
  1110.             {
  1111.                 bLoadComplete = FALSE;
  1112.                 continue;
  1113.             }
  1114.             
  1115.             // add new image to the ImageManager, along with the array index, 
  1116.             // which is referred by callout entries
  1117.             m_lpViewManager->AddImage( pView,( INT )i );
  1118.         }
  1119.     }
  1120.  
  1121.     // second pass to process all overlays
  1122.     for( i = 0; i < num_elements; i++ )
  1123.     {
  1124.         // check to see if the element is a control overlay entry
  1125.         if( m_lpDidImgHeader->lprgImageInfoArray[i].dwFlags & DIDIFT_OVERLAY )
  1126.         {
  1127.             pCallout = DidcvCallout::Create( &( m_lpDidImgHeader->lprgImageInfoArray[i] ) );
  1128.  
  1129.             if( NULL == pCallout )
  1130.             {
  1131.                 bLoadComplete = FALSE;
  1132.                 continue;
  1133.             }
  1134.             
  1135.             // try to get the appropriate view, by the offset in the image array
  1136.             pView = m_lpViewManager->GetImageByOffset( m_lpDidImgHeader->lprgImageInfoArray[i].dwViewID );
  1137.  
  1138.             if( NULL == pView )
  1139.             {
  1140.                 bLoadComplete = FALSE;
  1141.                 continue;
  1142.             }
  1143.  
  1144.             // add new image to the ImageManager, along with the array index, 
  1145.             // which is referred by callout entries
  1146.             m_lpCalloutManager->AddCallout( pCallout, pView->GetID() );
  1147.         }
  1148.     }
  1149.  
  1150.     // free unused dynamic memory
  1151.     m_lpCalloutManager->TrimArrays();
  1152.  
  1153.     // appropriate error code for bLoadComplete != TRUE is not returned at this time
  1154.     return S_OK;
  1155. }
  1156.  
  1157.  
  1158.  
  1159.  
  1160. //-----------------------------------------------------------------------------
  1161. // Name: CalcSizes()
  1162. // Desc: helper function to determine the number of views and callouts in
  1163. //       in the image info array.
  1164. //-----------------------------------------------------------------------------
  1165. VOID DIDCfgView::CalcSizes( const DIDEVICEIMAGEINFO* lprgImageInfoArray, 
  1166.                             DWORD dwNumElements, LPDWORD lpNumViews, 
  1167.                             LPDWORD lpNumCallouts, LPDWORD lpNumDistinctObjID )
  1168. {
  1169.     DWORD i, j;
  1170.  
  1171.     // set everything to 0
  1172.     *lpNumViews = *lpNumCallouts = *lpNumDistinctObjID = 0;
  1173.  
  1174.     for( i = 0; i < dwNumElements; i++ )
  1175.     {
  1176.         // figure out how many of each
  1177.         if( lprgImageInfoArray[i].dwFlags & DIDIFT_CONFIGURATION )
  1178.           ( *lpNumViews ) ++;
  1179.         else if( lprgImageInfoArray[i].dwFlags & DIDIFT_OVERLAY )
  1180.         {
  1181.           ( *lpNumCallouts ) ++;
  1182.  
  1183.             // find to see if dwObjID unique so far
  1184.             for( j = 0; j < i; j++ )
  1185.                 if( lprgImageInfoArray[j].dwObjID == lprgImageInfoArray[i].dwObjID )
  1186.                     break;
  1187.  
  1188.             if( j == i ) // current id unique
  1189.               ( *lpNumDistinctObjID )++;
  1190.         }
  1191.     }
  1192. }
  1193.  
  1194.  
  1195.  
  1196.  
  1197. //-----------------------------------------------------------------------------
  1198. // Name: enum DidcvEnumDataType
  1199. // Desc: constants for the dwType member of the DidcvEnumDeviceData
  1200. //-----------------------------------------------------------------------------
  1201. enum DidcvEnumDataType
  1202. {
  1203.     DIDCV_EDT_COUNT = 1,    // count
  1204.     DIDCV_EDT_SAVE  = 2     // save each item
  1205. };
  1206.  
  1207.  
  1208.  
  1209.  
  1210. //-----------------------------------------------------------------------------
  1211. // Name: IsObjectOnExcludeList()
  1212. // Desc: Exclude these objects from the view
  1213. //-----------------------------------------------------------------------------
  1214. BOOL IsObjectOnExcludeList( DWORD dwOfs )
  1215. {
  1216.     if (dwOfs == DIK_PREVTRACK  ||
  1217.         dwOfs == DIK_NEXTTRACK  ||
  1218.         dwOfs == DIK_MUTE       ||
  1219.         dwOfs == DIK_CALCULATOR ||
  1220.         dwOfs == DIK_PLAYPAUSE  ||
  1221.         dwOfs == DIK_MEDIASTOP  ||
  1222.         dwOfs == DIK_VOLUMEDOWN ||
  1223.         dwOfs == DIK_VOLUMEUP   ||
  1224.         dwOfs == DIK_WEBHOME    ||
  1225.         dwOfs == DIK_SLEEP      ||
  1226.         dwOfs == DIK_WEBSEARCH  ||
  1227.         dwOfs == DIK_WEBFAVORITES ||
  1228.         dwOfs == DIK_WEBREFRESH ||
  1229.         dwOfs == DIK_WEBSTOP    ||
  1230.         dwOfs == DIK_WEBFORWARD ||
  1231.         dwOfs == DIK_WEBBACK    ||
  1232.         dwOfs == DIK_MYCOMPUTER ||
  1233.         dwOfs == DIK_MAIL       ||
  1234.         dwOfs == DIK_MEDIASELECT)
  1235.         return TRUE;
  1236.  
  1237.     return FALSE;
  1238. }
  1239.  
  1240.  
  1241.  
  1242.  
  1243. //-----------------------------------------------------------------------------
  1244. // Name: DidcvEnumDeviceObjectsCallback()
  1245. // Desc: enumerates the objects( keys) on an device
  1246. //-----------------------------------------------------------------------------
  1247. BOOL CALLBACK DidcvEnumDeviceObjectsCallback( LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef )
  1248. {
  1249.     // get the struct that is passed in
  1250.     DidcvCustomViewInfo* lpData =( DidcvCustomViewInfo* ) pvRef;
  1251.     if( NULL == lpData )
  1252.         return DIENUM_STOP;
  1253.  
  1254.     // Exclude certain keys on advanced keyboards
  1255.     if( IsObjectOnExcludeList( lpddoi->dwOfs ) )
  1256.         return DIENUM_CONTINUE;
  1257.  
  1258.     if( lpData->dwType == DIDCV_EDT_COUNT )
  1259.     {
  1260.         // simply count
  1261.         lpData->dwCount++;
  1262.     }
  1263.     else if( lpData->dwType == DIDCV_EDT_SAVE )
  1264.     {
  1265.         if( lpData->dwSize < lpData->dwCount )
  1266.         {
  1267.             // instantiate new object instance
  1268.             lpData->rgObjData[lpData->dwSize] = new DIDEVICEOBJECTINSTANCE;
  1269.             memcpy( lpData->rgObjData[lpData->dwSize], lpddoi, sizeof( DIDEVICEOBJECTINSTANCE ) );
  1270.             lpData->dwSize++;
  1271.         }
  1272.         else
  1273.         {
  1274.             // this should not happen
  1275.             return DIENUM_STOP;
  1276.         }
  1277.     }
  1278.     else
  1279.         return DIENUM_STOP;
  1280.  
  1281.     return DIENUM_CONTINUE;
  1282. }
  1283.  
  1284.  
  1285.  
  1286.  
  1287. //-----------------------------------------------------------------------------
  1288. // Name: InitCustomViews()
  1289. // Desc: initializes custom views by retrieving device data, and calling
  1290. //       ConstructCustomView() to make views using bitmap images for
  1291. //       the device controls 
  1292. //-----------------------------------------------------------------------------
  1293. HRESULT DIDCfgView::InitCustomViews( LPDIRECTINPUTDEVICE8 lpDevice, BOOL bUseInternal )
  1294. {
  1295.     HRESULT hr;
  1296.  
  1297.     // reset the info
  1298.     if( m_lpCustomViewInfo )
  1299.         m_lpCustomViewInfo->CleanUp();
  1300.     else
  1301.     {
  1302.         m_lpCustomViewInfo = new DidcvCustomViewInfo;
  1303.         if( NULL == m_lpCustomViewInfo )
  1304.             return DIERR_OUTOFMEMORY;
  1305.     }
  1306.  
  1307.     // get a count of how many controls there are
  1308.     m_lpCustomViewInfo->dwType = DIDCV_EDT_COUNT;
  1309.  
  1310.     if( bUseInternal )
  1311.     {
  1312.         if( m_lpCalloutManager == NULL )
  1313.             return DIERR_INVALIDPARAM;
  1314.  
  1315.         // count internal objects that have action mapping
  1316.         m_lpCalloutManager->EnumObjects( lpDevice, DidcvEnumDeviceObjectsCallback, 
  1317.                                          m_lpCustomViewInfo, TRUE );
  1318.     }
  1319.     else
  1320.     {
  1321.         // count from device
  1322.         lpDevice->EnumObjects( DidcvEnumDeviceObjectsCallback, m_lpCustomViewInfo, DIDFT_ALL );
  1323.     }
  1324.  
  1325.     if( m_lpCustomViewInfo->dwCount == 0 )
  1326.     {
  1327.         m_lpCustomViewInfo->CleanUp();
  1328.         return DIERR_INVALIDPARAM;
  1329.     }
  1330.  
  1331.     // do a second time to get the objects
  1332.     m_lpCustomViewInfo->dwType = DIDCV_EDT_SAVE;
  1333.     m_lpCustomViewInfo->rgObjData = new LPDIDEVICEOBJECTINSTANCE[m_lpCustomViewInfo->dwCount];
  1334.     if( NULL == m_lpCustomViewInfo->rgObjData )
  1335.     {
  1336.         m_lpCustomViewInfo->CleanUp();
  1337.         return DIERR_OUTOFMEMORY;
  1338.     }
  1339.  
  1340.     if( bUseInternal )
  1341.     {
  1342.         if( m_lpCalloutManager == NULL )
  1343.             return DIERR_INVALIDPARAM;
  1344.  
  1345.         // get the internal objects that have action mapping
  1346.         m_lpCalloutManager->EnumObjects( lpDevice, DidcvEnumDeviceObjectsCallback, 
  1347.                                          m_lpCustomViewInfo, TRUE );
  1348.     }
  1349.     else
  1350.     {
  1351.         // get a list of all objects for the device
  1352.         lpDevice->EnumObjects( DidcvEnumDeviceObjectsCallback, 
  1353.                                m_lpCustomViewInfo, DIDFT_ALL );
  1354.     }
  1355.  
  1356.     if( m_lpCustomViewInfo->dwSize == 0 )
  1357.     {
  1358.         m_lpCustomViewInfo->CleanUp();
  1359.         return DIERR_INVALIDPARAM;
  1360.     }
  1361.  
  1362.     // build the custom views
  1363.     if( FAILED( hr = BuildCustomViews() ) )
  1364.     {
  1365.         m_lpCustomViewInfo->CleanUp();
  1366.         return hr;
  1367.     }
  1368.  
  1369.     return S_OK;
  1370. }
  1371.  
  1372.  
  1373.  
  1374.  
  1375. //-----------------------------------------------------------------------------
  1376. // Name: BuildCustomViews()
  1377. // Desc: makes custom views
  1378. //-----------------------------------------------------------------------------
  1379. HRESULT DIDCfgView::BuildCustomViews()
  1380. {
  1381.     DidcvView* pView;
  1382.     DidcvCallout* pCallout;
  1383.     DWORD dwNumViews, dwStartIndex, dwFinishIndex;
  1384.     DWORD i, j;
  1385.     DIDEVICEIMAGEINFO devImageInfo;
  1386.  
  1387.     // pre-condition of this method - m_lpCustomViewInfo must be loaded
  1388.     assert( m_lpCustomViewInfo && m_lpCustomViewInfo->rgObjData );
  1389.  
  1390.     // calculate the number of views needed
  1391.     dwNumViews = DidcvCustomView::CalcNumViews( m_lpCustomViewInfo->dwSize );
  1392.     assert( dwNumViews );
  1393.  
  1394.     // reset
  1395.     m_lpViewManager->CleanUp();
  1396.     m_lpCalloutManager->CleanUp();
  1397.  
  1398.     // set the initial capacity
  1399.     if( FALSE == m_lpViewManager->SetCapacity( dwNumViews ) )
  1400.         return DIERR_OUTOFMEMORY;
  1401.  
  1402.     if( FALSE == m_lpCalloutManager->SetCapacity( m_lpCustomViewInfo->dwSize, 
  1403.                                                   m_lpCustomViewInfo->dwSize, dwNumViews ) )
  1404.         return DIERR_OUTOFMEMORY;
  1405.  
  1406.     dwStartIndex = 0;
  1407.     for( i = 0; i < dwNumViews; i++ )
  1408.     {
  1409.         // create views, each for a section of object array
  1410.         pView = DidcvCustomView::Create( m_lpCustomViewInfo, dwStartIndex, 
  1411.                                          &dwFinishIndex );
  1412.         if( NULL == pView )
  1413.             return DIERR_OUTOFMEMORY;
  1414.  
  1415.         // add the view to the manager
  1416.         if( FAILED( m_lpViewManager->AddImage( pView ) ) )
  1417.         {
  1418.             delete pView;
  1419.             continue;
  1420.         }
  1421.  
  1422.         for( j = dwStartIndex; j <= dwFinishIndex; j++ )
  1423.         {
  1424.             ZeroMemory( &devImageInfo, sizeof( DIDEVICEIMAGEINFO ) );
  1425.  
  1426.             // construct our own image info
  1427.             devImageInfo.dwFlags = DIDIFT_OVERLAY;
  1428.             // figure out the callout information for each object
  1429.             DidcvCustomView::CalcImageInfo( j, &( devImageInfo.rcOverlay ), 
  1430.                                             &( devImageInfo.dwcValidPts ),
  1431.                                             devImageInfo.rgptCalloutLine, 
  1432.                                             &( devImageInfo.rcCalloutRect ) );
  1433.             devImageInfo.dwTextAlign = DIDAL_LEFTALIGNED;
  1434.             devImageInfo.dwObjID = m_lpCustomViewInfo->rgObjData[j]->dwType;
  1435.  
  1436.             // create the callout and add
  1437.             pCallout = DidcvCallout::Create( &devImageInfo );
  1438.             m_lpCalloutManager->AddCallout( pCallout, pView->GetID() );
  1439.         }
  1440.  
  1441.         dwStartIndex = dwFinishIndex + 1;
  1442.     }
  1443.  
  1444.     return S_OK;
  1445. }
  1446.  
  1447.  
  1448.  
  1449.  
  1450. //-----------------------------------------------------------------------------
  1451. // Name: CopyActionMap()
  1452. // Desc: copies a DIACTIONFORMAT
  1453. //-----------------------------------------------------------------------------
  1454. BOOL DIDCfgView::CopyActionMap( LPDIACTIONFORMAT lpDiaf )
  1455. {
  1456.     if( m_lpDiaf )
  1457.     {
  1458.         // free the DIACTIONFORMAT
  1459.         if( m_lpDiaf->rgoAction )
  1460.             delete [] m_lpDiaf->rgoAction;
  1461.         delete m_lpDiaf;
  1462.         m_lpDiaf = NULL;
  1463.     }
  1464.  
  1465.     if( lpDiaf == NULL )
  1466.         return TRUE;
  1467.  
  1468.     m_lpDiaf = new DIACTIONFORMAT;
  1469.     if( m_lpDiaf == NULL )
  1470.         return FALSE;
  1471.  
  1472.     // copy the DIACTIONFORMAT
  1473.     memcpy( m_lpDiaf, lpDiaf, sizeof( DIACTIONFORMAT ) );
  1474.     if( lpDiaf->rgoAction )
  1475.     {
  1476.         // copy the internal array
  1477.         m_lpDiaf->rgoAction = new DIACTION[lpDiaf->dwNumActions];
  1478.         if( m_lpDiaf->rgoAction == NULL )
  1479.             return FALSE;
  1480.  
  1481.         memcpy( m_lpDiaf->rgoAction, lpDiaf->rgoAction, 
  1482.                 sizeof( DIACTION ) * lpDiaf->dwNumActions );
  1483.     }
  1484.  
  1485.     return TRUE;
  1486. }
  1487.  
  1488.  
  1489.  
  1490.  
  1491. //-----------------------------------------------------------------------------
  1492. // Name: CleanUp()
  1493. // Desc: release the resource for the CustomViewInfo
  1494. //-----------------------------------------------------------------------------
  1495. void DidcvCustomViewInfo::CleanUp()
  1496. {
  1497.     // free the custom view data
  1498.     if( rgObjData )
  1499.     {
  1500.         DWORD i;
  1501.         // free each item
  1502.         for( i = 0; i < dwSize; i++)
  1503.             if( rgObjData[i] )
  1504.                 delete rgObjData[i];
  1505.  
  1506.         // free the array
  1507.         delete [] rgObjData;
  1508.         rgObjData = NULL;
  1509.     }
  1510.  
  1511.     dwCount = 0;
  1512.     dwSize = 0;
  1513. }
  1514.  
  1515.  
  1516.  
  1517.  
  1518. //-----------------------------------------------------------------------------
  1519. // Name: DidcvBitmap()
  1520. // Desc: Constructor
  1521. //-----------------------------------------------------------------------------
  1522. DidcvBitmap::DidcvBitmap()
  1523.     : m_hbitmap( NULL ),
  1524.       m_lpBits( NULL )
  1525. {
  1526.     ZeroMemory( &m_size, sizeof( SIZE ) );
  1527.  
  1528.     // register with the alpha blend module
  1529.     DidcvAlphaBlend::AddClient();
  1530. }
  1531.  
  1532.  
  1533.  
  1534.  
  1535. //-----------------------------------------------------------------------------
  1536. // Name: ~DidcvBitmap()
  1537. // Desc: Destructor
  1538. //-----------------------------------------------------------------------------
  1539. DidcvBitmap::~DidcvBitmap()
  1540. {
  1541.     CleanUp();
  1542.  
  1543.     // release the alpha blending module
  1544.     DidcvAlphaBlend::ReleaseClient();
  1545. }
  1546.  
  1547.  
  1548.  
  1549.  
  1550. //-----------------------------------------------------------------------------
  1551. // Name: GetSize()
  1552. // Desc: retrieves the size of the bitmap - return FALSE if there is no bitmap
  1553. //-----------------------------------------------------------------------------
  1554. BOOL DidcvBitmap::GetSize( SIZE* lpSize ) const
  1555. {
  1556.     if( NULL == m_hbitmap )
  1557.         return FALSE;
  1558.  
  1559.     memcpy( lpSize, &m_size, sizeof( SIZE ) );
  1560.     return TRUE;
  1561. }
  1562.  
  1563.  
  1564.  
  1565.  
  1566. //-----------------------------------------------------------------------------
  1567. // Name: Draw()
  1568. // Desc: Draws onto a HDC, at( xStart, yStart )
  1569. //-----------------------------------------------------------------------------
  1570. BOOL DidcvBitmap::Draw( HDC hDC, INT xStart, INT yStart )
  1571. {
  1572.     if( NULL == m_hbitmap )
  1573.         return FALSE;
  1574.  
  1575.     BITMAP bm;
  1576.     HDC hdcMem;
  1577.     POINT ptSize, ptOrg;
  1578.  
  1579.     // create memory DC
  1580.     hdcMem = CreateCompatibleDC( hDC );
  1581.     SelectObject( hdcMem, m_hbitmap );
  1582.     SetMapMode( hdcMem, GetMapMode( hDC ) );
  1583.  
  1584.     // get bitmap info
  1585.     GetObject( m_hbitmap, sizeof( BITMAP ),( LPVOID ) &bm );
  1586.  
  1587.     ptSize.x = bm.bmWidth;
  1588.     ptSize.y = bm.bmHeight;
  1589.     DPtoLP( hDC, &ptSize, 1 );
  1590.  
  1591.     ptOrg.x = 0;
  1592.     ptOrg.y = 0;
  1593.     DPtoLP( hdcMem, &ptOrg, 1 );
  1594.  
  1595.     // blit
  1596.     BitBlt( hDC, xStart, yStart, ptSize.x, ptSize.y, 
  1597.             hdcMem, ptOrg.x, ptOrg.y, SRCCOPY );
  1598.  
  1599.     // free the memory DC
  1600.     DeleteDC( hdcMem );
  1601.  
  1602.     return TRUE;
  1603. }
  1604.  
  1605.  
  1606.  
  1607.  
  1608. //-----------------------------------------------------------------------------
  1609. // Name: Blend()
  1610. // Desc: draw the bitmap into HDC with alpha blending( xStart, yStart )
  1611. //-----------------------------------------------------------------------------
  1612. BOOL DidcvBitmap::Blend( HDC hDC, INT xStart, INT yStart )
  1613. {
  1614.     return DidcvAlphaBlend::Blend( hDC, xStart, yStart, 
  1615.                                    m_size.cx, m_size.cy, m_hbitmap, &m_size );
  1616. }
  1617.  
  1618.  
  1619.  
  1620.  
  1621. //-----------------------------------------------------------------------------
  1622. // Name: Blend()
  1623. // Desc: blend this bitmap unto the image
  1624. //-----------------------------------------------------------------------------
  1625. BOOL DidcvBitmap::Blend( VOID* lpBits, INT xStart, INT yStart, INT width, INT height )
  1626. {
  1627.     return DidcvAlphaBlend::Blend( lpBits, xStart, yStart, width, height, 
  1628.                                    m_lpBits, m_size.cx, m_size.cy );
  1629. }
  1630.  
  1631.  
  1632.  
  1633.  
  1634. //-----------------------------------------------------------------------------
  1635. // Name: GetHandle()
  1636. // Desc: return the GDI HBITMAP handle
  1637. //-----------------------------------------------------------------------------
  1638. HBITMAP DidcvBitmap::GetHandle()
  1639. {
  1640.     return m_hbitmap;
  1641. }
  1642.  
  1643.  
  1644.  
  1645.  
  1646. //-----------------------------------------------------------------------------
  1647. // Name: GetBits()
  1648. // Desc: returns a pointer to the bits
  1649. //-----------------------------------------------------------------------------
  1650. LPVOID DidcvBitmap::GetBits()
  1651. {
  1652.     return m_lpBits;
  1653. }
  1654.  
  1655.  
  1656.  
  1657.  
  1658. //-----------------------------------------------------------------------------
  1659. // Name: Create()
  1660. // Desc: static function to instantiate a bitmap object from a pathname
  1661. //-----------------------------------------------------------------------------
  1662. DidcvBitmap* DidcvBitmap::Create( LPCTSTR tszFilename )
  1663. {
  1664.     return CreateViaD3dx( tszFilename );
  1665. }
  1666.  
  1667.  
  1668.  
  1669.  
  1670. //-----------------------------------------------------------------------------
  1671. // Name: Create()
  1672. // Desc: static function to instantiate a bitmap object from dimensions
  1673. //-----------------------------------------------------------------------------
  1674. DidcvBitmap* DidcvBitmap::Create( INT width, INT height )
  1675. {
  1676.     BITMAPINFO bmi;
  1677.     DidcvBitmap* bm;
  1678.     HBITMAP hbm;
  1679.     VOID* lpBits;
  1680.  
  1681.     // sanity check
  1682.     if( width <= 0 || height <= 0 )
  1683.         return NULL;
  1684.  
  1685.     // make the header
  1686.     ZeroMemory( &bmi, sizeof( BITMAPINFO ) );
  1687.     bmi.bmiHeader.biSize = sizeof( bmi.bmiHeader );
  1688.     bmi.bmiHeader.biWidth = width;
  1689.     bmi.bmiHeader.biHeight = height;
  1690.     bmi.bmiHeader.biPlanes = 1;
  1691.     bmi.bmiHeader.biBitCount = 32;
  1692.     bmi.bmiHeader.biCompression = BI_RGB;
  1693.     bmi.bmiHeader.biSizeImage = 0;
  1694.     bmi.bmiHeader.biXPelsPerMeter = 0;
  1695.     bmi.bmiHeader.biYPelsPerMeter = 0;
  1696.     bmi.bmiHeader.biClrUsed = 0;
  1697.     bmi.bmiHeader.biClrImportant = 0;
  1698.  
  1699.     // create a DIBSection
  1700.     hbm = CreateDIBSection( NULL, &bmi, DIB_RGB_COLORS, &lpBits, NULL, 0 );
  1701.     if( hbm == NULL )
  1702.         return NULL;
  1703.  
  1704.     // allocate an object
  1705.     bm = new DidcvBitmap;
  1706.     if( NULL == bm )
  1707.         return NULL;
  1708.  
  1709.     // set the members
  1710.     bm->m_hbitmap;
  1711.     bm->m_lpBits = lpBits;
  1712.     bm->m_size.cx = width;
  1713.     bm->m_size.cy = height;
  1714.  
  1715.     return bm;
  1716. }
  1717.  
  1718.  
  1719.  
  1720.  
  1721.  
  1722. //-----------------------------------------------------------------------------
  1723. // Name: CleanUp()
  1724. // Desc: helper function to free resources
  1725. //-----------------------------------------------------------------------------
  1726. void DidcvBitmap::CleanUp()
  1727. {
  1728.     if( m_hbitmap )
  1729.     {
  1730.         DeleteObject( m_hbitmap );
  1731.         m_hbitmap = NULL;
  1732.     }
  1733.  
  1734.     m_lpBits = NULL;
  1735.     ZeroMemory( &m_size, sizeof( SIZE ) );
  1736. }
  1737.  
  1738.  
  1739.  
  1740.  
  1741. //-----------------------------------------------------------------------------
  1742. // Name: FigureSize()
  1743. // Desc: determines the size of the bitmap
  1744. //-----------------------------------------------------------------------------
  1745. void DidcvBitmap::FigureSize()
  1746. {
  1747.     BITMAP bm;
  1748.  
  1749.     if( NULL == m_hbitmap )
  1750.         return;
  1751.  
  1752.     if( 0 == GetObject( ( HGDIOBJ ) m_hbitmap, sizeof( BITMAP ),( LPVOID ) &bm ) )
  1753.         return;
  1754.  
  1755.     m_size.cx = abs( bm.bmWidth );
  1756.     m_size.cy = abs( bm.bmHeight );
  1757. }
  1758.  
  1759.  
  1760.  
  1761.  
  1762. //-----------------------------------------------------------------------------
  1763. // static members of DidcvAlphaBlend
  1764. //-----------------------------------------------------------------------------
  1765. DIDCV_ALPHABLEND DidcvAlphaBlend::s_alphaBlendProc = NULL;
  1766. HMODULE          DidcvAlphaBlend::s_hDll = NULL;
  1767. DWORD            DidcvAlphaBlend::s_dwNumClients = 0;
  1768.  
  1769.  
  1770.  
  1771.  
  1772. //-----------------------------------------------------------------------------
  1773. // Name: AddClient()
  1774. // Desc: static alpha blending initialization function
  1775. //       this bumps the reference count by one for each time it is called
  1776. //-----------------------------------------------------------------------------
  1777. BOOL DidcvAlphaBlend::AddClient()
  1778. {
  1779.     // try to the AlphaBlend function
  1780.     if( s_alphaBlendProc == NULL )
  1781.     {
  1782.         s_hDll = LoadLibrary( DIDCV_ALPHABLEND_DLL_NAME );
  1783.  
  1784.         if( s_hDll )
  1785.         {
  1786.             s_alphaBlendProc =( DIDCV_ALPHABLEND ) GetProcAddress( s_hDll, 
  1787.                                 DIDCV_ALPHABLEND_PROC_NAME );
  1788.             if( !s_alphaBlendProc )
  1789.             { 
  1790.                 FreeLibrary( s_hDll );
  1791.                 s_hDll = NULL;
  1792.             }
  1793.         }
  1794.     }
  1795.  
  1796.     // bump the reference count
  1797.     s_dwNumClients ++;
  1798.  
  1799.     return( s_alphaBlendProc != NULL );
  1800. }
  1801.  
  1802.  
  1803.  
  1804.  
  1805. //-----------------------------------------------------------------------------
  1806. // Name: ReleaseClient()
  1807. // Desc: static alpha blend function called when a client detach
  1808. //-----------------------------------------------------------------------------
  1809. BOOL DidcvAlphaBlend::ReleaseClient()
  1810. {
  1811.     if( s_dwNumClients )
  1812.         s_dwNumClients --;
  1813.  
  1814.     // if reference count 0, then free resources
  1815.     if( s_dwNumClients == 0 )
  1816.     {
  1817.         s_alphaBlendProc = NULL;
  1818.  
  1819.         if( s_hDll )
  1820.         {
  1821.             FreeLibrary( s_hDll );
  1822.             s_hDll = NULL;
  1823.         }
  1824.     }
  1825.  
  1826.     return TRUE;
  1827. }
  1828.  
  1829.  
  1830.  
  1831. //-----------------------------------------------------------------------------
  1832. // Name: Blend()
  1833. // Desc: blends images by hand
  1834. //-----------------------------------------------------------------------------
  1835. BOOL DidcvAlphaBlend::Blend( VOID* lpDestBits, INT xStart, INT yStart, 
  1836.                              INT destWidth, INT destHeight, VOID* lpSrcBits, 
  1837.                              INT srcWidth, INT srcHeight )
  1838. {
  1839.     if( !lpDestBits || !lpSrcBits )
  1840.         return FALSE;
  1841.  
  1842.     // calculate the strides
  1843.     INT destStride = destWidth * 4;
  1844.     INT destOffset = xStart * 4;
  1845.     INT srcStride = srcWidth * 4;
  1846.     INT i, j;
  1847.  
  1848.     // clip the rectangle to draw to if necessary
  1849.     if( ( xStart + srcWidth ) >( destWidth ) )
  1850.         srcWidth = destWidth - xStart;
  1851.     if( ( yStart + srcHeight ) >( destHeight ) )
  1852.         srcHeight = destHeight - yStart;
  1853.  
  1854.     // the DIB bits are is indexed from bottom, left corner, so need to reverse horizontally
  1855.     BYTE* pDestStart = ( BYTE* ) lpDestBits + 
  1856.                        ( ( destHeight - yStart - 1 ) * destStride ) + destOffset;
  1857.     BYTE* pSrcStart =( BYTE* ) lpSrcBits + ( srcHeight - 1 ) * srcStride;
  1858.     BYTE destAlpha, srcAlpha;
  1859.  
  1860.     for( i = 0; i < srcHeight; i++ )
  1861.     {
  1862.         for( j = 0; j < srcStride; j += 4 )
  1863.         {
  1864.             // calculate src and dest alpha
  1865.             destAlpha = 0xff - pSrcStart[j + 3];
  1866.             srcAlpha = pSrcStart[j + 3];
  1867.  
  1868.             if( !srcAlpha ) continue;
  1869.             if( !destAlpha )
  1870.                 *(( DWORD* )&pDestStart[j]) = *((DWORD *)&pSrcStart[j]);
  1871.             else
  1872.             {
  1873.                 // set the R, G, B components
  1874.                 pDestStart [j] =( pDestStart[j] * destAlpha + pSrcStart[j] * srcAlpha ) / 0xff;
  1875.                 pDestStart [j+1] =( pDestStart[j+1] * destAlpha + pSrcStart[j+1] * srcAlpha ) / 0xff;
  1876.                 pDestStart [j+2] =( pDestStart[j+2] * destAlpha + pSrcStart[j+2] * srcAlpha ) / 0xff;
  1877.             }
  1878.         }
  1879.  
  1880.         // advance the pointers
  1881.         pDestStart -= destStride;
  1882.         pSrcStart -= srcStride;
  1883.     }
  1884.  
  1885.     return TRUE;
  1886. }
  1887.  
  1888.  
  1889.  
  1890.  
  1891. //-----------------------------------------------------------------------------
  1892. // Name: Blend()
  1893. // Desc: blends a bitmap into the HDC
  1894. //-----------------------------------------------------------------------------
  1895. BOOL DidcvAlphaBlend::Blend( HDC hDC, INT xStart, INT yStart, INT width, 
  1896.                              INT height, HBITMAP hbitmap, const SIZE* lpSize )
  1897. {
  1898.     if( hDC == NULL || hbitmap == NULL || lpSize == NULL )
  1899.         return FALSE;
  1900.  
  1901. #if( WINVER >= 0x400 )
  1902.  
  1903.     HDC hDCbm = CreateCompatibleDC( hDC );
  1904.     if( hDCbm == NULL )
  1905.         return FALSE;
  1906.  
  1907. // this is done to resolve differences in header files
  1908. #ifdef AC_SRC_ALPHA
  1909.     BLENDFUNCTION blendfn = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
  1910. #else
  1911.     BLENDFUNCTION blendfn = { AC_SRC_OVER, 0, 255, 0x1 };
  1912. #endif
  1913.  
  1914.     HGDIOBJ hOldBitmap = SelectObject( hDCbm, hbitmap );
  1915.     BOOL bRet = s_alphaBlendProc( hDC, xStart, yStart, width, height, 
  1916.                                   hDCbm, 0, 0, lpSize->cx, lpSize->cy, blendfn );
  1917.     SelectObject( hDCbm, hOldBitmap ); 
  1918.     DeleteDC( hDCbm );
  1919.  
  1920.     return TRUE;
  1921.  
  1922. #else
  1923.  
  1924.     return FALSE;
  1925.  
  1926. #endif
  1927.  
  1928. }
  1929.  
  1930.  
  1931.  
  1932.  
  1933. //-----------------------------------------------------------------------------
  1934. // Name: DidcvCallout()
  1935. // Desc: Constructor
  1936. //-----------------------------------------------------------------------------
  1937. DidcvCallout::DidcvCallout()
  1938.     : m_nViewRef( DIDCV_INVALID_ID ),
  1939.       m_lpDataRef( NULL ),
  1940.       m_lpOverlayBitmap( NULL )
  1941. {
  1942.     ZeroMemory( &m_devImgInfo, sizeof( DIDEVICEIMAGEINFO ) );
  1943. }
  1944.  
  1945.  
  1946.  
  1947.  
  1948. //-----------------------------------------------------------------------------
  1949. // Name: ~DidcvCallout()
  1950. // Desc: destructor
  1951. //-----------------------------------------------------------------------------
  1952. DidcvCallout::~DidcvCallout()
  1953. {
  1954.     if( m_lpOverlayBitmap )
  1955.     {
  1956.         delete m_lpOverlayBitmap;
  1957.         m_lpOverlayBitmap = NULL;
  1958.     }
  1959. }
  1960.  
  1961.  
  1962.  
  1963.  
  1964. //-----------------------------------------------------------------------------
  1965. // Name: GetObjID()
  1966. // Desc: returns the object ID
  1967. //-----------------------------------------------------------------------------
  1968. DWORD DidcvCallout::GetObjID() const
  1969. {
  1970.     return m_devImgInfo.dwObjID;
  1971. }
  1972.  
  1973.  
  1974.  
  1975.  
  1976. //-----------------------------------------------------------------------------
  1977. // Name: GetOverlayRect()
  1978. // Desc: returns the overlay rect for the callout
  1979. //-----------------------------------------------------------------------------
  1980. const RECT & DidcvCallout::GetOverlayRect() const
  1981. {
  1982.     return m_devImgInfo.rcOverlay;
  1983. }
  1984.  
  1985.  
  1986.  
  1987.  
  1988. //-----------------------------------------------------------------------------
  1989. // Name: GetCalloutRect()
  1990. // Desc: returns the callout rect, where the action text is displayed
  1991. //-----------------------------------------------------------------------------
  1992. const RECT & DidcvCallout::GetCalloutRect() const
  1993. {
  1994.     return m_devImgInfo.rcCalloutRect;
  1995. }
  1996.  
  1997.  
  1998.  
  1999.  
  2000. //-----------------------------------------------------------------------------
  2001. // Name: GetCalloutLine()
  2002. // Desc: returns the callout line segments as a const array
  2003. //-----------------------------------------------------------------------------
  2004. const POINT* DidcvCallout::GetCalloutLine( DWORD* lpNumPts ) const
  2005. {
  2006.     if( NULL != lpNumPts )
  2007.         *lpNumPts = m_devImgInfo.dwcValidPts;
  2008.  
  2009.     return m_devImgInfo.rgptCalloutLine;
  2010. }
  2011.  
  2012.  
  2013.  
  2014.  
  2015. //-----------------------------------------------------------------------------
  2016. // Name: GetTextAlign()
  2017. // Desc: return the text alignment for the callout
  2018. //-----------------------------------------------------------------------------
  2019. DWORD DidcvCallout::GetTextAlign() const
  2020. {
  2021.     return m_devImgInfo.dwTextAlign;
  2022. }
  2023.  
  2024.  
  2025.  
  2026.  
  2027. //-----------------------------------------------------------------------------
  2028. // Name: GetOverlayOffset()
  2029. // Desc: returns the index of the callout in the original image info array
  2030. //       returned by DirectInputDevice8::GetImage()
  2031. //-----------------------------------------------------------------------------
  2032. DWORD DidcvCallout::GetOverlayOffset() const
  2033. {
  2034.     return m_devImgInfo.dwViewID;
  2035. }
  2036.  
  2037.  
  2038.  
  2039.  
  2040. //-----------------------------------------------------------------------------
  2041. // Name: GetAssociatedViewID()
  2042. // Desc: returns the internally assigned( by DIDCfgView ) identifier of a
  2043. //       view that this callout is assicated with
  2044. //-----------------------------------------------------------------------------
  2045. INT DidcvCallout::GetAssociatedViewID() const
  2046. {
  2047.     return m_nViewRef;
  2048. }
  2049.  
  2050.  
  2051.  
  2052.  
  2053. //-----------------------------------------------------------------------------
  2054. // Name: SetAssociatedViewID()
  2055. // Desc: sets the view with which this callout is associated with
  2056. //-----------------------------------------------------------------------------
  2057. void DidcvCallout::SetAssociatedViewID( INT nViewRef )
  2058. {
  2059.     m_nViewRef = nViewRef;
  2060. }
  2061.  
  2062.  
  2063.  
  2064.  
  2065. //-----------------------------------------------------------------------------
  2066. // Name: HitTest()
  2067. // Desc: tests to determines whether a point is contained the associated
  2068. //       regions of this callout.  coordinates are relative to the left top
  2069. //       corner of the image
  2070. //-----------------------------------------------------------------------------
  2071. DWORD DidcvCallout::HitTest( LPPOINT lpPt ) const
  2072. {
  2073.     if( NULL == lpPt )
  2074.         return FALSE;
  2075.  
  2076.     // if in overlay rectangle, then hit
  2077.     //    if( PtInRect( &( m_devImgInfo.rcOverlay ), *lpPt ) )
  2078.     //        return TRUE;
  2079.  
  2080.     // if in callout rectangle, then hit
  2081.     if( PtInRect( &( m_devImgInfo.rcCalloutRect ), *lpPt ) )
  2082.         return TRUE;
  2083.  
  2084.     return FALSE;
  2085. }
  2086.  
  2087.  
  2088.  
  2089.  
  2090. //-----------------------------------------------------------------------------
  2091. // Name: DrawOverlay()
  2092. // Desc: draws the overlay image
  2093. //-----------------------------------------------------------------------------
  2094. DWORD DidcvCallout::DrawOverlay( HDC hDC, VOID* lpBits, INT width, 
  2095.                                  INT height, const POINT* ptOrigin )
  2096. {
  2097.     BOOL res = FALSE;
  2098.  
  2099.     if( m_lpOverlayBitmap )
  2100.     {
  2101.         // alpha blend with pointers only
  2102.         if( lpBits )
  2103.             res = m_lpOverlayBitmap->Blend( lpBits, 
  2104.                         m_devImgInfo.rcOverlay.left + ptOrigin->x, 
  2105.                         m_devImgInfo.rcOverlay.top  + ptOrigin->y, 
  2106.                         width, height );
  2107.  
  2108.         if( !res )
  2109.         {
  2110.             // try alpha blending with hDC
  2111.             res = m_lpOverlayBitmap->Blend( hDC, m_devImgInfo.rcOverlay.left, 
  2112.                                             m_devImgInfo.rcOverlay.top );
  2113.         }
  2114.     }
  2115.  
  2116.     return res;
  2117. }
  2118.  
  2119.  
  2120.  
  2121.  
  2122. //-----------------------------------------------------------------------------
  2123. // Name: SetDataRef()
  2124. // Desc: attach a pointer to the callout data relevant to this callout
  2125. //-----------------------------------------------------------------------------
  2126. void DidcvCallout::SetDataRef( const DidcvCalloutData* lpData )
  2127. {
  2128.     m_lpDataRef = lpData;
  2129. }
  2130.  
  2131.  
  2132.  
  2133.  
  2134. //-----------------------------------------------------------------------------
  2135. // Name: GetDataRef()
  2136. // Desc: retrieved the the data reference stored with this callout
  2137. //-----------------------------------------------------------------------------
  2138. const DidcvCalloutData* DidcvCallout::GetDataRef() const
  2139. {
  2140.     return m_lpDataRef;
  2141. }
  2142.  
  2143.  
  2144.  
  2145.  
  2146. //-----------------------------------------------------------------------------
  2147. // Name: Create()
  2148. // Desc: static function for instantiating a DidcvCallout
  2149. //-----------------------------------------------------------------------------
  2150. DidcvCallout* DidcvCallout::Create( LPDIDEVICEIMAGEINFO lpDevImgInfo )
  2151. {
  2152.     DidcvCallout* lpCallout = NULL;
  2153.  
  2154.     if( NULL == lpDevImgInfo )
  2155.         return NULL;
  2156.  
  2157.     // allocate
  2158.     lpCallout = new DidcvCallout;
  2159.  
  2160.     if( NULL == lpCallout )
  2161.         return NULL;
  2162.  
  2163.     // copy the device image info
  2164.     memcpy( &( lpCallout->m_devImgInfo ), lpDevImgInfo, sizeof( DIDEVICEIMAGEINFO ) );
  2165.  
  2166.     if( lpDevImgInfo->tszImagePath )
  2167.     {
  2168.         // load the overlay
  2169.         lpCallout->m_lpOverlayBitmap = DidcvBitmap::Create( lpDevImgInfo->tszImagePath );
  2170.     }
  2171.  
  2172.     return lpCallout;
  2173. }
  2174.  
  2175.  
  2176.  
  2177.  
  2178. //-----------------------------------------------------------------------------
  2179. // Name: DidcvCalloutManager()
  2180. // Desc: Constructor
  2181. //-----------------------------------------------------------------------------
  2182. DidcvCalloutManager::DidcvCalloutManager() 
  2183.     : m_calloutList( DIDCV_DEFAULT_CALLOUT_MANAGER_ARRAY_SIZE ),
  2184.       m_calloutSetListByObjID( DIDCV_DEFAULT_CALLOUT_MANAGER_ARRAY_SIZE ),
  2185.       m_calloutSetListByView( DIDCV_DEFAULT_CALLOUT_MANAGER_ARRAY_SIZE )
  2186. { }
  2187.  
  2188.  
  2189.  
  2190.  
  2191. //-----------------------------------------------------------------------------
  2192. // Name: ~DidcvCalloutManager()
  2193. // Desc: destructor
  2194. //-----------------------------------------------------------------------------
  2195. DidcvCalloutManager::~DidcvCalloutManager()
  2196. {
  2197.     CleanUp();
  2198. }
  2199.  
  2200.  
  2201.  
  2202.  
  2203. //-----------------------------------------------------------------------------
  2204. // Name: CleanUp()
  2205. // Desc: reset the callout manager, freeing resources
  2206. //-----------------------------------------------------------------------------
  2207. void DidcvCalloutManager::CleanUp()
  2208. {
  2209.     UINT i;
  2210.  
  2211.     // free the entries
  2212.     for( i = 0; i < m_calloutList.Size(); i++ )
  2213.         if( m_calloutList[i] )
  2214.             delete m_calloutList[i];
  2215.  
  2216.     // free the view callout set
  2217.     for( i = 0; i < m_calloutSetListByView.Size(); i++ )
  2218.         if( m_calloutSetListByView[i] )
  2219.             delete m_calloutSetListByView[i];
  2220.  
  2221.     // free the obj id callout set
  2222.     for( i = 0; i < m_calloutSetListByObjID.Size(); i++ )
  2223.     {
  2224.         if( m_calloutSetListByObjID[i] )
  2225.         {
  2226.             DidcvCalloutData* lpCalloutData = 
  2227.               ( DidcvCalloutData* ) m_calloutSetListByObjID[i]->GetData();
  2228.  
  2229.             // is there is data attached, deallocate it
  2230.             if( lpCalloutData )
  2231.             {
  2232.                 if( lpCalloutData->lpState )
  2233.                     delete lpCalloutData->lpState;
  2234.  
  2235.                 if( lpCalloutData->lpActionMap )
  2236.                     delete lpCalloutData->lpActionMap;
  2237.  
  2238.                 delete lpCalloutData;
  2239.             }
  2240.  
  2241.             delete m_calloutSetListByObjID[i];
  2242.         }
  2243.     }
  2244.  
  2245.     // set the array size to 0
  2246.     m_calloutList.SetSize( 0 );
  2247.     m_calloutSetListByObjID.SetSize( 0 );
  2248.     m_calloutSetListByView.SetSize( 0 );
  2249. }
  2250.  
  2251.  
  2252.  
  2253.  
  2254. //-----------------------------------------------------------------------------
  2255. // Name: SetCapacity()
  2256. // Desc: sets the capacity in advance
  2257. //-----------------------------------------------------------------------------
  2258. BOOL DidcvCalloutManager::SetCapacity( DWORD dwNumCallouts, DWORD dwNumUniqueObjID, 
  2259.                                        DWORD dwNumViews, BOOL bDeleteContent )
  2260. {
  2261.     if( bDeleteContent )
  2262.         CleanUp();
  2263.  
  2264.     m_calloutList.SetSize( dwNumCallouts );
  2265.     m_calloutSetListByObjID.SetSize( dwNumUniqueObjID );
  2266.     m_calloutSetListByView.SetSize( dwNumViews );
  2267.  
  2268.     return TRUE;
  2269. }
  2270.  
  2271.  
  2272.  
  2273.  
  2274. //-----------------------------------------------------------------------------
  2275. // Name: AddCallout()
  2276. // Desc: adds a callout object to be stored and managed by this object
  2277. //-----------------------------------------------------------------------------
  2278. BOOL DidcvCalloutManager::AddCallout( DidcvCallout* lpCallout, INT nView )
  2279. {
  2280.     DidcvCalloutSet*  lpViewSet  = NULL;
  2281.     DidcvCalloutSet*  lpObjIDSet = NULL;
  2282.     DidcvCalloutData* lpData     = NULL;
  2283.  
  2284.     // sanity check
  2285.     if( NULL == lpCallout || lpCallout->GetObjID() == 0 || nView < 0 )
  2286.         return FALSE;
  2287.  
  2288.     // append to complete list
  2289.     m_calloutList.PushBack( lpCallout );
  2290.  
  2291.     // ----------- organize by view
  2292.  
  2293.     // look to see if CalloutSet exist for the view
  2294.     lpViewSet = Find( m_calloutSetListByView,( DWORD ) nView );
  2295.  
  2296.     // no set exist - new view
  2297.     if( NULL == lpViewSet )
  2298.     {
  2299.         lpViewSet = new DidcvCalloutSet;
  2300.         lpViewSet->SetIdentifier( ( DWORD ) nView );
  2301.         m_calloutSetListByView.PushBack( lpViewSet );
  2302.     }
  2303.  
  2304.     // append callout to the view set
  2305.     lpViewSet->AddCallout( lpCallout );
  2306.  
  2307.     // ----------- organize by object id
  2308.  
  2309.     // look to see if CalloutSet exist for the ObjID
  2310.     lpObjIDSet = Find( m_calloutSetListByObjID, lpCallout->GetObjID() );
  2311.  
  2312.     if( NULL == lpObjIDSet )
  2313.     {
  2314.         // new set of callout
  2315.         lpObjIDSet = new DidcvCalloutSet;
  2316.         lpObjIDSet->SetIdentifier( lpCallout->GetObjID() );
  2317.         // allocate new data to be associated
  2318.         lpObjIDSet->SetData( lpData = new DidcvCalloutData( 
  2319.             new DidcvCalloutState( DIDCV_ALL_CALLOUT_STATE_SET ),
  2320.             NULL ) );
  2321.         m_calloutSetListByObjID.PushBack( lpObjIDSet );
  2322.     }
  2323.     else
  2324.     {
  2325.         lpData =( DidcvCalloutData* ) lpObjIDSet->GetData();
  2326.     }
  2327.  
  2328.     // append callout
  2329.     lpObjIDSet->AddCallout( lpCallout );
  2330.  
  2331.     // set data reference
  2332.     lpCallout->SetDataRef( lpData );
  2333.  
  2334.     return TRUE;
  2335. }
  2336.  
  2337.  
  2338.  
  2339.  
  2340. //-----------------------------------------------------------------------------
  2341. // Name: GetObjectIDByLocation()
  2342. // Desc: given a point( in image coordinate ) and a view, returns a callout 
  2343. //     ( if any ) that contains the point.
  2344. //-----------------------------------------------------------------------------
  2345. DWORD DidcvCalloutManager::GetObjectIDByLocation( LPPOINT lpPt, INT nView )
  2346. {
  2347.     UINT i, size;
  2348.     DidcvCalloutSet* lpViewSet = NULL;
  2349.  
  2350.     // sanity check
  2351.     if( NULL == lpPt || nView < 0 )
  2352.         return 0;
  2353.  
  2354.     // look for the the callout set by view
  2355.     lpViewSet = Find( m_calloutSetListByView,( DWORD )nView );
  2356.  
  2357.     // if not found, return
  2358.     if( NULL == lpViewSet )
  2359.         return 0;
  2360.  
  2361.     // obtain a const reference, fast + safe
  2362.     const GwArray <DidcvCallout *> & arr = lpViewSet->GetInternalArrayRef();
  2363.  
  2364.     size = arr.Size();
  2365.  
  2366.     // loop through the callouts
  2367.     for( i = 0; i < size; i++ )
  2368.     {
  2369.         // return the first hit
  2370.         if( arr[i]->HitTest( lpPt ) != 0 )
  2371.             return arr[i]->GetObjID();
  2372.     }
  2373.  
  2374.     // no hits
  2375.     return 0;
  2376. }
  2377.  
  2378.  
  2379.  
  2380.  
  2381. //-----------------------------------------------------------------------------
  2382. // Name: SetCalloutState()
  2383. // Desc: set the state for a particular callout
  2384. //-----------------------------------------------------------------------------
  2385. BOOL DidcvCalloutManager::SetCalloutState( const DidcvCalloutState* lpCalloutState, 
  2386.                                            DWORD dwObjID )
  2387. {
  2388.     DidcvCalloutData* lpInternalCalloutData;
  2389.  
  2390.     // sanity check
  2391.     if( NULL == lpCalloutState )
  2392.         return FALSE;
  2393.  
  2394.     // get the data associated with the object
  2395.     lpInternalCalloutData = GetCalloutData( dwObjID );
  2396.  
  2397.     // not found
  2398.     if( NULL == lpInternalCalloutData )
  2399.         return FALSE;
  2400.  
  2401.     // set the internal state to the new state
  2402.     lpInternalCalloutData->lpState->SmartSet( lpCalloutState );
  2403.  
  2404.     return TRUE;
  2405. }
  2406.  
  2407.  
  2408.  
  2409.  
  2410. //-----------------------------------------------------------------------------
  2411. // Name: SetCalloutState()
  2412. // Desc: set the state for a particular callout
  2413. //-----------------------------------------------------------------------------
  2414. BOOL DidcvCalloutManager::SetAllCalloutState( const DidcvCalloutState* lpCalloutState )
  2415. {
  2416.     DidcvCalloutData* lpInternalCalloutData;
  2417.     UINT i;
  2418.  
  2419.     // sanity check
  2420.     if( NULL == lpCalloutState )
  2421.         return FALSE;
  2422.  
  2423.     for( i = 0; i < m_calloutSetListByObjID.Size(); i++ )
  2424.     {
  2425.         // get the data associated with the object
  2426.         lpInternalCalloutData =( DidcvCalloutData* ) m_calloutSetListByObjID[i]->GetData();
  2427.  
  2428.         // not found
  2429.         if( NULL == lpInternalCalloutData )
  2430.         {
  2431.             // internal error
  2432.             continue;
  2433.         }
  2434.  
  2435.         // set the internal state to the new state
  2436.         lpInternalCalloutData->lpState->SmartSet( lpCalloutState );
  2437.     }
  2438.  
  2439.     return TRUE;
  2440. }
  2441.  
  2442.  
  2443.  
  2444.  
  2445. //-----------------------------------------------------------------------------
  2446. // Name: GetCalloutState()
  2447. // Desc: retrieves the state for a given callout
  2448. //-----------------------------------------------------------------------------
  2449. BOOL DidcvCalloutManager::GetCalloutState( DidcvCalloutState* lpCalloutState, 
  2450.                                            DWORD dwObjID )
  2451. {
  2452.     DidcvCalloutData* lpInternalCalloutData;
  2453.  
  2454.     if( NULL == lpCalloutState )
  2455.         return FALSE;
  2456.  
  2457.     // get the data associated with the object
  2458.     lpInternalCalloutData = GetCalloutData( dwObjID );
  2459.  
  2460.     // not found
  2461.     if( NULL == lpInternalCalloutData )
  2462.         return FALSE;
  2463.  
  2464.     // copy the internal state
  2465.     lpCalloutState->Copy( lpInternalCalloutData->lpState );
  2466.  
  2467.     return TRUE;
  2468. }
  2469.  
  2470.  
  2471.  
  2472.  
  2473. //-----------------------------------------------------------------------------
  2474. // Name: SetActionMap()
  2475. // Desc: sets the action mapping for a particular callout
  2476. //-----------------------------------------------------------------------------
  2477. BOOL DidcvCalloutManager::SetActionMap( const LPDIACTION lpAction, DWORD dwObjID )
  2478. {
  2479.     DidcvCalloutSet* lpCalloutSet = NULL;
  2480.     DidcvCalloutData* lpInternalCalloutData = NULL;
  2481.     DidcvActionMap* lpActionMap = NULL;
  2482.  
  2483.     // find the set associated with the control
  2484.     lpCalloutSet = Find( m_calloutSetListByObjID, dwObjID );
  2485.  
  2486.     // not found
  2487.     if( NULL == lpCalloutSet )
  2488.         return FALSE;
  2489.  
  2490.     // get the data associated with the object
  2491.     lpInternalCalloutData =( DidcvCalloutData* ) lpCalloutSet->GetData();
  2492.  
  2493.     // every set should have a callout data reference, if not - internal error
  2494.     assert ( lpInternalCalloutData != NULL );
  2495.  
  2496.     if( NULL == lpAction )
  2497.     {
  2498.         // if lpAction is NULL, then reset the action map
  2499.         if( lpInternalCalloutData->lpActionMap )
  2500.         {
  2501.             delete lpInternalCalloutData->lpActionMap;
  2502.             lpInternalCalloutData->lpActionMap = NULL;
  2503.         }
  2504.  
  2505.         lpActionMap;
  2506.     }
  2507.     else
  2508.     {
  2509.         // allocate, if necessary
  2510.         if( NULL == lpInternalCalloutData->lpActionMap )
  2511.             lpActionMap = lpInternalCalloutData->lpActionMap = new DidcvActionMap;
  2512.  
  2513.         // store the information
  2514.         memcpy( &( lpInternalCalloutData->lpActionMap->dia ), 
  2515.                 lpAction, sizeof( DIACTION ) );
  2516.     }
  2517.  
  2518.     return TRUE;
  2519. }
  2520.  
  2521.  
  2522.  
  2523.  
  2524. //-----------------------------------------------------------------------------
  2525. // Name: GetActionMap()
  2526. // Desc: retrieves the action map for a particular callout
  2527. //-----------------------------------------------------------------------------
  2528. BOOL DidcvCalloutManager::GetActionMap( DidcvActionMap* lpActionMap, DWORD dwObjID )
  2529. {
  2530.     DidcvCalloutData* lpInternalCalloutData;
  2531.  
  2532.     // get the data associated with the object
  2533.     lpInternalCalloutData = GetCalloutData( dwObjID );
  2534.  
  2535.     // not found
  2536.     if( NULL == lpInternalCalloutData || NULL == lpInternalCalloutData->lpActionMap )
  2537.         return FALSE;
  2538.  
  2539.     // copy internal data to be returned
  2540.     lpActionMap->Copy( lpInternalCalloutData->lpActionMap );
  2541.  
  2542.     return TRUE;
  2543. }
  2544.  
  2545.  
  2546.  
  2547.  
  2548. //-----------------------------------------------------------------------------
  2549. // Name: GetNumUniqueCallouts()
  2550. // Desc: returns the number of unique callouts
  2551. //-----------------------------------------------------------------------------
  2552. UINT DidcvCalloutManager::GetNumUniqueCallouts() const
  2553. {
  2554.     return m_calloutSetListByObjID.Size();
  2555. }
  2556.  
  2557.  
  2558.  
  2559.  
  2560. //-----------------------------------------------------------------------------
  2561. // Name: ClearAllActionMaps()
  2562. // Desc: resets( and frees ) all action maps associated with all callouts in
  2563. //       the manager
  2564. //-----------------------------------------------------------------------------
  2565. void DidcvCalloutManager::ClearAllActionMaps()
  2566. {
  2567.     UINT i;
  2568.     DidcvCalloutData* lpInternalCalloutData;
  2569.  
  2570.     // run through callout set list
  2571.     for( i = 0; i < m_calloutSetListByObjID.Size(); i++ )
  2572.     {
  2573.         // get the data associated with each
  2574.         lpInternalCalloutData =( DidcvCalloutData* ) m_calloutSetListByObjID[i]->GetData();
  2575.         
  2576.         if( lpInternalCalloutData->lpActionMap )
  2577.         {
  2578.             // free and reset action maps
  2579.             delete lpInternalCalloutData->lpActionMap;
  2580.             lpInternalCalloutData->lpActionMap = NULL;
  2581.         }
  2582.     }
  2583. }
  2584.  
  2585.  
  2586.  
  2587.  
  2588. //-----------------------------------------------------------------------------
  2589. // Name: EnumObjects()
  2590. // Desc: enumerates the list of objects - the dwMapOnly specifies if only
  2591. //       objects with action assign
  2592. //-----------------------------------------------------------------------------
  2593. BOOL DidcvCalloutManager::EnumObjects( LPDIRECTINPUTDEVICE8 lpDevice, 
  2594.                                        LPDIENUMDEVICEOBJECTSCALLBACK lpCallback, 
  2595.                                        LPVOID pvRef, DWORD dwMapOnly )
  2596. {
  2597.     UINT i;
  2598.     DidcvCalloutData* lpData;
  2599.     DIDEVICEOBJECTINSTANCE objInst;
  2600.  
  2601.     if( lpDevice == NULL || lpCallback == NULL )
  2602.         return FALSE;
  2603.  
  2604.     // go through list of unique callouts
  2605.     for( i = 0; i < m_calloutSetListByObjID.Size(); i++ )
  2606.     {
  2607.         // get the data associated with the callout set
  2608.         lpData =( DidcvCalloutData* ) m_calloutSetListByObjID[i]->GetData();
  2609.  
  2610.         // if do all or if action mapped
  2611.         if( !dwMapOnly || lpData->lpActionMap )
  2612.         {
  2613.             ZeroMemory( &objInst, sizeof( DIDEVICEOBJECTINSTANCE ) );
  2614.             objInst.dwSize = sizeof( DIDEVICEOBJECTINSTANCE );
  2615.  
  2616.             // get the info about the object from the device
  2617.             lpDevice->GetObjectInfo( &objInst, 
  2618.                         m_calloutSetListByObjID[i]->GetIdentifier(), DIPH_BYID );
  2619.             lpCallback( &objInst, pvRef );
  2620.         }
  2621.     }
  2622.     
  2623.     return TRUE;
  2624. }
  2625.  
  2626.  
  2627.  
  2628.  
  2629. //-----------------------------------------------------------------------------
  2630. // Name: CalcCanBeCollapsed()
  2631. // Desc: figures out if there are any unmapped callouts
  2632. //-----------------------------------------------------------------------------
  2633. BOOL DidcvCalloutManager::CalcCanBeCollapsed()
  2634. {
  2635.     UINT i;
  2636.     DidcvCalloutData* lpData;
  2637.  
  2638.     for( i = 0; i < m_calloutSetListByObjID.Size(); i ++ )
  2639.     {
  2640.         lpData =( DidcvCalloutData* ) m_calloutSetListByObjID[i]->GetData();
  2641.  
  2642.         // if we find any non-mapped callouts
  2643.         if( lpData->lpActionMap == NULL )
  2644.             return TRUE;
  2645.     }
  2646.  
  2647.     return FALSE;
  2648. }
  2649.  
  2650.  
  2651.  
  2652.  
  2653. //-----------------------------------------------------------------------------
  2654. // Name: TrimArrays()
  2655. // Desc: trims the internal array( and frees unnecessary memory )
  2656. //-----------------------------------------------------------------------------
  2657. void DidcvCalloutManager::TrimArrays()
  2658. {
  2659.     // this shouldn't have to do anything if the sizes were preset
  2660.     m_calloutList.Trim();
  2661.     m_calloutSetListByObjID.Trim();
  2662.     m_calloutSetListByView.Trim();
  2663.  
  2664.     UINT i;
  2665.  
  2666.     for( i = 0; i < m_calloutSetListByObjID.Size(); i ++ )
  2667.         m_calloutSetListByObjID[i]->TrimArrays();
  2668.  
  2669.     for( i = 0; i < m_calloutSetListByView.Size(); i ++ )
  2670.         m_calloutSetListByView[i]->TrimArrays();
  2671. }
  2672.  
  2673.  
  2674.  
  2675.  
  2676. //-----------------------------------------------------------------------------
  2677. // Name: GetCalloutDataRef()
  2678. // Desc: returns the( const ) data associated with a particular callout
  2679. //-----------------------------------------------------------------------------
  2680. const DidcvCalloutData* DidcvCalloutManager::GetCalloutDataRef( DWORD dwObjID ) const
  2681. {
  2682.     return GetCalloutData( dwObjID );
  2683. }
  2684.  
  2685.  
  2686.  
  2687.  
  2688. //-----------------------------------------------------------------------------
  2689. // Name: GetCalloutSetByView()
  2690. // Desc: return the callout set for a given view, if any
  2691. //-----------------------------------------------------------------------------
  2692. const DidcvCalloutSet* DidcvCalloutManager::GetCalloutSetByView( INT nView ) const
  2693. {
  2694.     return Find( m_calloutSetListByView,( DWORD ) nView );
  2695. }
  2696.  
  2697.  
  2698.  
  2699.  
  2700. //-----------------------------------------------------------------------------
  2701. // Name: GetCalloutSetByObjID()
  2702. // Desc: returns the callout set for a given callout, if any
  2703. //-----------------------------------------------------------------------------
  2704. const DidcvCalloutSet* DidcvCalloutManager::GetCalloutSetByObjID( DWORD dwObjID ) const
  2705. {
  2706.     return Find( m_calloutSetListByView, dwObjID );
  2707. }
  2708.  
  2709.  
  2710.  
  2711.  
  2712. //-----------------------------------------------------------------------------
  2713. // Name: Find()
  2714. // Desc: helper function to find a callout set from an array, using 
  2715. //       an identifier
  2716. //-----------------------------------------------------------------------------
  2717. DidcvCalloutSet* DidcvCalloutManager::Find( const GwArray <DidcvCalloutSet *> & arr, 
  2718.                                             DWORD dwIdentifier ) const
  2719. {
  2720.     // TODO: this function can be optimized if needed
  2721.     UINT i, size;
  2722.  
  2723.     size = arr.Size();
  2724.  
  2725.     for( i = 0; i < size; i++ )
  2726.     {
  2727.         if( arr[i]->GetIdentifier() == dwIdentifier )
  2728.             return arr[i];
  2729.     }
  2730.  
  2731.     return NULL;
  2732. }
  2733.  
  2734.  
  2735.  
  2736.  
  2737. //-----------------------------------------------------------------------------
  2738. // Name: GetCalloutData()
  2739. // Desc: helper function that returns the callout data for a given callout
  2740. //-----------------------------------------------------------------------------
  2741. DidcvCalloutData* DidcvCalloutManager::GetCalloutData( DWORD dwObjID ) const
  2742. {
  2743.     DidcvCalloutData* lpData;
  2744.     DidcvCalloutSet* lpCalloutSet;
  2745.  
  2746.     // find the set of callout with the id
  2747.     lpCalloutSet = Find( m_calloutSetListByObjID, dwObjID );
  2748.  
  2749.     // if not found
  2750.     if( NULL == lpCalloutSet )
  2751.         return NULL;
  2752.  
  2753.     // return the data associated with the object
  2754.     lpData =( DidcvCalloutData* ) lpCalloutSet->GetData();
  2755.  
  2756.     if( NULL == lpData || NULL == lpData->lpState )
  2757.     {
  2758.         // internal error, must handle differently
  2759.         assert( 0 );
  2760.         return NULL;
  2761.     }
  2762.  
  2763.     return lpData;
  2764. }
  2765.  
  2766.  
  2767.  
  2768.  
  2769. //-----------------------------------------------------------------------------
  2770. // Name: DidcvCalloutSet()
  2771. // Desc: Constructor
  2772. //-----------------------------------------------------------------------------
  2773. DidcvCalloutSet::DidcvCalloutSet()
  2774.     : m_calloutList( DIDCV_DEFAULT_CALLOUT_SET_ARRAY_SIZE ),
  2775.       m_dwSetID( 0 ),
  2776.       m_lpData( NULL )
  2777. { }
  2778.  
  2779.  
  2780.  
  2781.  
  2782. //-----------------------------------------------------------------------------
  2783. // Name: ~DidcvCalloutSet()
  2784. // Desc: destructor
  2785. //-----------------------------------------------------------------------------
  2786. DidcvCalloutSet::~DidcvCalloutSet()
  2787. {
  2788.     CleanUp();
  2789. }
  2790.  
  2791.  
  2792.  
  2793.  
  2794. //-----------------------------------------------------------------------------
  2795. // Name: CleanUp()
  2796. // Desc: resets the object, and frees any resources
  2797. //-----------------------------------------------------------------------------
  2798. void DidcvCalloutSet::CleanUp()
  2799. {
  2800.     // set the array back to default size
  2801.     m_calloutList.SetSize( 0 );
  2802.  
  2803.     // reset the set id
  2804.     m_dwSetID = 0;
  2805.  
  2806.     // reset the data pointer
  2807.     m_lpData = NULL;
  2808. }
  2809.  
  2810.  
  2811.  
  2812.  
  2813. //-----------------------------------------------------------------------------
  2814. // Name: TrimArrays()
  2815. // Desc: resize arrays to free unused memory
  2816. //-----------------------------------------------------------------------------
  2817. void DidcvCalloutSet::TrimArrays()
  2818. {
  2819.     m_calloutList.Trim();
  2820. }
  2821.  
  2822.  
  2823.  
  2824. //-----------------------------------------------------------------------------
  2825. // Name: AddCallout()
  2826. // Desc: adds a callout reference to the set
  2827. //-----------------------------------------------------------------------------
  2828. BOOL DidcvCalloutSet::AddCallout( DidcvCallout* lpCallout )
  2829. {
  2830.     // if NULL, return FALSE
  2831.     if( NULL == lpCallout )
  2832.         return FALSE;
  2833.  
  2834.     // append to list
  2835.     m_calloutList.PushBack( lpCallout );
  2836.  
  2837.     return TRUE;
  2838. }
  2839.  
  2840.  
  2841.  
  2842.  
  2843. //-----------------------------------------------------------------------------
  2844. // Name: Apply()
  2845. // Desc: using a instantiation of DidcvCalloutApplicant, applies it to every
  2846. //       every callout in the group
  2847. //-----------------------------------------------------------------------------
  2848. void DidcvCalloutSet::Apply( DidcvCalloutApplicant* lpCalloutApp )
  2849. {
  2850.     UINT i, size;
  2851.  
  2852.     size = m_calloutList.Size();
  2853.  
  2854.     // loop through entries, and apply each
  2855.     for( i = 0; i < size; i++ )
  2856.     {
  2857.         // if FALSE is returned, then stop
  2858.         if( FALSE == lpCalloutApp->Apply( m_calloutList[i] ) )
  2859.             break;
  2860.     }
  2861. }
  2862.  
  2863.  
  2864.  
  2865.  
  2866. //-----------------------------------------------------------------------------
  2867. // Name: GetInternalArray()
  2868. // Desc: returns a const reference to the array that stores the callout
  2869. //       references
  2870. //-----------------------------------------------------------------------------
  2871. const GwArray <DidcvCallout *> & DidcvCalloutSet::GetInternalArrayRef() const
  2872. {
  2873.     return m_calloutList;
  2874. }
  2875.  
  2876.  
  2877.  
  2878.  
  2879. //-----------------------------------------------------------------------------
  2880. // Name: SetIdentifier()
  2881. // Desc: assigned a unique identifier to the set
  2882. //-----------------------------------------------------------------------------
  2883. void DidcvCalloutSet::SetIdentifier( DWORD dwID )
  2884. {
  2885.     m_dwSetID = dwID;
  2886. }
  2887.  
  2888.  
  2889.  
  2890.  
  2891. //-----------------------------------------------------------------------------
  2892. // Name: GetIdentifier()
  2893. // Desc: returns the identifier associated with this set
  2894. //-----------------------------------------------------------------------------
  2895. DWORD DidcvCalloutSet::GetIdentifier() const
  2896. {
  2897.     return m_dwSetID;
  2898. }
  2899.  
  2900.  
  2901.  
  2902.  
  2903. //-----------------------------------------------------------------------------
  2904. // Name: SetData()
  2905. // Desc: attach a void pointer with this set
  2906. //-----------------------------------------------------------------------------
  2907. void DidcvCalloutSet::SetData( void* lpData )
  2908. {
  2909.     m_lpData = lpData;
  2910. }
  2911.  
  2912.  
  2913.  
  2914.  
  2915. //-----------------------------------------------------------------------------
  2916. // Name: GetData()
  2917. // Desc: returns the data associated with this set
  2918. //-----------------------------------------------------------------------------
  2919. void* DidcvCalloutSet::GetData() const
  2920. {
  2921.     return m_lpData;
  2922. }
  2923.  
  2924.  
  2925.  
  2926.  
  2927. //-----------------------------------------------------------------------------
  2928. // Name: PutLinePoint()
  2929. // Desc: draws a line to a point
  2930. //-----------------------------------------------------------------------------
  2931. void PutLinePoint( HDC hDC, POINT p )
  2932. {
  2933.     MoveToEx( hDC, p.x, p.y, NULL );
  2934.     LineTo( hDC, p.x + 1, p.y );
  2935. }
  2936.  
  2937.  
  2938.  
  2939.  
  2940. //-----------------------------------------------------------------------------
  2941. // Name: SmartSet()
  2942. // Desc: copies valid members of other
  2943. //-----------------------------------------------------------------------------
  2944. void DidcvCalloutState::SmartSet( const DidcvCalloutState* other )
  2945. {
  2946.     if( other->dwFlags & DIDCV_DRAWCALLOUT )
  2947.         bDrawCallout = other->bDrawCallout;
  2948.  
  2949.     if( other->dwFlags & DIDCV_DRAWOVERLAY )
  2950.         bDrawOverlay = other->bDrawOverlay;
  2951.  
  2952.     if( other->dwFlags & DIDCV_DRAWHIGHLIGHT )
  2953.         bDrawHighlight = other->bDrawHighlight;
  2954.  
  2955.     if( other->dwFlags & DIDCV_DRAWEMPTYCALLOUT )
  2956.         bDrawEmptyCallout = other->bDrawEmptyCallout;
  2957.  
  2958.     if( other->dwFlags & DIDCV_DRAWFULLNAME )
  2959.         bDrawFullname = other->bDrawFullname;
  2960. }
  2961.  
  2962.  
  2963.  
  2964.  
  2965. //-----------------------------------------------------------------------------
  2966. // Name: MakeFlag()
  2967. // Desc: makes a DWORD flag
  2968. //-----------------------------------------------------------------------------
  2969. DWORD DidcvCalloutState::MakeFlag() const
  2970. {
  2971.     DWORD dwExtFlags = 0;
  2972.  
  2973.     if( ( dwFlags & DIDCV_DRAWCALLOUT ) && bDrawCallout )
  2974.         dwExtFlags |= DIDCV_DRAWCALLOUT;
  2975.  
  2976.     if( ( dwFlags & DIDCV_DRAWOVERLAY ) && bDrawOverlay )
  2977.         dwExtFlags |= DIDCV_DRAWOVERLAY;
  2978.  
  2979.     if( ( dwFlags & DIDCV_DRAWHIGHLIGHT ) && bDrawHighlight )
  2980.         dwExtFlags |= DIDCV_DRAWHIGHLIGHT;
  2981.  
  2982.     if( ( dwFlags & DIDCV_DRAWEMPTYCALLOUT ) && bDrawEmptyCallout )
  2983.         dwExtFlags |= DIDCV_DRAWEMPTYCALLOUT;
  2984.  
  2985.     if( ( dwFlags & DIDCV_DRAWFULLNAME ) && bDrawFullname )
  2986.         dwExtFlags |= DIDCV_DRAWFULLNAME;
  2987.  
  2988.     return dwExtFlags;
  2989. }
  2990.  
  2991.  
  2992.  
  2993.  
  2994. //-----------------------------------------------------------------------------
  2995. // Name: SetFlag()
  2996. // Desc: given a flag, sets the members
  2997. //-----------------------------------------------------------------------------
  2998. void DidcvCalloutState::SetFlag( DWORD dwExtFlags )
  2999. {
  3000.     dwFlags = DIDCV_ALL_CALLOUT_STATE_SET;
  3001.  
  3002.     bDrawCallout = ( dwExtFlags & DIDCV_DRAWCALLOUT ) != 0;
  3003.     bDrawOverlay = ( dwExtFlags & DIDCV_DRAWOVERLAY ) != 0;
  3004.     bDrawHighlight = ( dwExtFlags & DIDCV_DRAWHIGHLIGHT ) != 0;
  3005.     bDrawEmptyCallout = ( dwExtFlags & DIDCV_DRAWEMPTYCALLOUT ) != 0;
  3006.     bDrawFullname = ( dwExtFlags & DIDCV_DRAWFULLNAME ) != 0;
  3007. }
  3008.  
  3009.  
  3010.  
  3011.  
  3012. //-----------------------------------------------------------------------------
  3013. // Name: DidcvPolyLineArrow()
  3014. // Desc: draws a line using an array of line segments, with optional shadows
  3015. //-----------------------------------------------------------------------------
  3016. void DidcvPolyLineArrow( HDC hDC, const POINT *rgpt, int nPoints, BOOL bDoShadow )
  3017. {
  3018.     int i;
  3019.  
  3020.     if( rgpt == NULL || nPoints < 1 )
  3021.         return;
  3022.  
  3023.     if( nPoints > 1 )
  3024.         for( i = 0; i < nPoints - 1; i++ )
  3025.         {
  3026.             SPOINT a = rgpt[i], b = rgpt[i + 1];
  3027.  
  3028.             if( bDoShadow )
  3029.             {
  3030.                 int rise = abs( b.y - a.y ), run = abs( b.x - a.x );
  3031.                 bool vert = rise > run;
  3032.                 int ord = vert ? 1 : 0;
  3033.                 int nord = vert ? 0 : 1;
  3034.                 
  3035.                 for( int o = -1; o <= 1; o += 2 )
  3036.                 {
  3037.                     SPOINT c( a ), d( b );
  3038.                     c.a[nord] += o;
  3039.                     d.a[nord] += o;
  3040.                     MoveToEx( hDC, c.x, c.y, NULL );
  3041.                     LineTo( hDC, d.x, d.y );
  3042.                 }
  3043.  
  3044.                 bool reverse = a.a[ord] > b.a[ord];
  3045.                 SPOINT e( reverse ? b : a ), f( reverse ? a : b );
  3046.                 e.a[ord] -= 1;
  3047.                 f.a[ord] += 1;
  3048.                 PutLinePoint( hDC, e );
  3049.                 PutLinePoint( hDC, f );
  3050.             }
  3051.             else
  3052.             {
  3053.                 MoveToEx( hDC, a.x, a.y, NULL );
  3054.                 LineTo( hDC, b.x, b.y );
  3055.             }
  3056.         }
  3057.  
  3058.     POINT z = rgpt[nPoints - 1];
  3059.  
  3060.     if( bDoShadow )
  3061.     {
  3062.         POINT pt[5] = {
  3063.             { z.x, z.y + 2 },
  3064.             { z.x + 2, z.y },
  3065.             { z.x, z.y - 2 },
  3066.             { z.x - 2, z.y }, };
  3067.         pt[4] = pt[0];
  3068.         Polyline( hDC, pt, 5 );
  3069.     }
  3070.     else
  3071.     {
  3072.         MoveToEx( hDC, z.x - 1, z.y, NULL );
  3073.         LineTo( hDC, z.x + 2, z.y );
  3074.         MoveToEx( hDC, z.x, z.y - 1, NULL );
  3075.         LineTo( hDC, z.x, z.y + 2 );
  3076.     }
  3077. }
  3078.  
  3079.  
  3080.  
  3081.  
  3082. //-----------------------------------------------------------------------------
  3083. // Name: DidcvCreateFont()
  3084. // Desc: Creates a GDI font object( code adapted from Charles Petzold )
  3085. //-----------------------------------------------------------------------------
  3086. HFONT DidcvCreateFont( HDC hdc, const TCHAR* szFaceName, int iDeciPtHeight, 
  3087.                        int iDeciPtWidth, int iAttributes, BOOL fLogRes)
  3088. {
  3089.      FLOAT      cxDpi, cyDpi ;
  3090.      HFONT      hFont ;
  3091.      LOGFONT    lf ;
  3092.      POINT      pt ;
  3093.      TEXTMETRIC tm ;
  3094.  
  3095.      SaveDC( hdc ) ;
  3096.  
  3097.      SetGraphicsMode( hdc, GM_ADVANCED ) ;
  3098.      ModifyWorldTransform( hdc, NULL, MWT_IDENTITY ) ;
  3099.      SetViewportOrgEx( hdc, 0, 0, NULL ) ;
  3100.      SetWindowOrgEx  ( hdc, 0, 0, NULL ) ;
  3101.  
  3102.      if( fLogRes)
  3103.      {
  3104.           cxDpi =( FLOAT) GetDeviceCaps( hdc, LOGPIXELSX ) ;
  3105.           cyDpi =( FLOAT) GetDeviceCaps( hdc, LOGPIXELSY ) ;
  3106.      }
  3107.      else
  3108.      {
  3109.           cxDpi =( FLOAT)( 25.4 * GetDeviceCaps( hdc, HORZRES ) /
  3110.                                   GetDeviceCaps( hdc, HORZSIZE ) ) ;
  3111.  
  3112.           cyDpi =( FLOAT)( 25.4 * GetDeviceCaps( hdc, VERTRES ) /
  3113.                                   GetDeviceCaps( hdc, VERTSIZE ) ) ;
  3114.      }
  3115.  
  3116.      pt.x =( int)( iDeciPtWidth  * cxDpi / 72 ) ;
  3117.      pt.y =( int)( iDeciPtHeight * cyDpi / 72 ) ;
  3118.  
  3119.      DPtoLP( hdc, &pt, 1) ;
  3120.  
  3121.      lf.lfHeight         = -( int)( fabs( pt.y) / 10.0 + 0.5 ) ;
  3122.      lf.lfWidth          = 0 ;
  3123.      lf.lfEscapement     = 0 ;
  3124.      lf.lfOrientation    = 0 ;
  3125.      lf.lfWeight         = iAttributes & DIDCV_FONT_BOLD      ? 700 : 0 ;
  3126.      lf.lfItalic         = iAttributes & DIDCV_FONT_ITALIC    ?   1 : 0 ;
  3127.      lf.lfUnderline      = iAttributes & DIDCV_FONT_UNDERLINE ?   1 : 0 ;
  3128.      lf.lfStrikeOut      = iAttributes & DIDCV_FONT_STRIKEOUT ?   1 : 0 ;
  3129.      lf.lfCharSet        = 0 ;
  3130.      lf.lfOutPrecision   = 0 ;
  3131.      lf.lfClipPrecision  = 0 ;
  3132.      lf.lfQuality        = 0 ;
  3133.      lf.lfPitchAndFamily = 0 ;
  3134.  
  3135.      _tcscpy( lf.lfFaceName, szFaceName ) ;
  3136.  
  3137.      hFont = CreateFontIndirect( &lf ) ;
  3138.  
  3139.      if( iDeciPtWidth != 0 )
  3140.      {
  3141.           hFont =( HFONT ) SelectObject( hdc, hFont );
  3142.           GetTextMetrics( hdc, &tm );
  3143.           DeleteObject( SelectObject( hdc, hFont ) ) ;
  3144.           lf.lfWidth =( int)( tm.tmAveCharWidth * fabs( pt.x ) / 
  3145.                               fabs( pt.y ) + 0.5 ) ;
  3146.  
  3147.           hFont = CreateFontIndirect( &lf ) ;
  3148.      }
  3149.  
  3150.      RestoreDC( hdc, -1) ;
  3151.  
  3152.      return hFont ;
  3153. }
  3154.  
  3155.  
  3156.  
  3157.  
  3158. //-----------------------------------------------------------------------------
  3159. // Name: DidcvView()
  3160. // Desc: Constructor
  3161. //-----------------------------------------------------------------------------
  3162. DidcvView::DidcvView()
  3163.     : m_nOffset( DIDCV_INVALID_ID ),
  3164.       m_nID( DIDCV_INVALID_ID )
  3165. { }
  3166.  
  3167.  
  3168.  
  3169.  
  3170. //-----------------------------------------------------------------------------
  3171. // Name: SetOffset()
  3172. // Desc: sets the offset from the original index returned by GetImage
  3173. //-----------------------------------------------------------------------------
  3174. void DidcvView::SetOffset( INT nOffset )
  3175. {
  3176.     m_nOffset = nOffset;
  3177. }
  3178.  
  3179.  
  3180.  
  3181.  
  3182. //-----------------------------------------------------------------------------
  3183. // Name: GetOffset()
  3184. // Desc: returns the original GetImage offset
  3185. //-----------------------------------------------------------------------------
  3186. INT DidcvView::GetOffset() const
  3187. {
  3188.     return m_nOffset;
  3189. }
  3190.  
  3191.  
  3192.  
  3193.  
  3194. //-----------------------------------------------------------------------------
  3195. // Name: SetID()
  3196. // Desc: sets the internally assigned unique identifier
  3197. //-----------------------------------------------------------------------------
  3198. void DidcvView::SetID( INT nID )
  3199. {
  3200.     m_nID = nID;
  3201. }
  3202.  
  3203.  
  3204.  
  3205.  
  3206. //-----------------------------------------------------------------------------
  3207. // Name: GetID()
  3208. // Desc: returns the internally assigned unique identifier
  3209. //-----------------------------------------------------------------------------
  3210. INT DidcvView::GetID() const
  3211. {
  3212.     return m_nID;
  3213. }
  3214.  
  3215.  
  3216.  
  3217.  
  3218. //-----------------------------------------------------------------------------
  3219. // Name: Create()
  3220. // Desc: static function to the instantiate a DidcvView object from filename
  3221. //-----------------------------------------------------------------------------
  3222. DidcvBitmapView* DidcvBitmapView::Create( LPCTSTR tszFilename, DWORD dwFlags )
  3223. {
  3224.     DidcvBitmapView* lpView;
  3225.     DidcvBitmap* lpBm;
  3226.  
  3227.     lpView = new DidcvBitmapView();
  3228.     if( NULL == lpView )
  3229.         return NULL;
  3230.  
  3231.     lpBm = DidcvBitmap::Create( tszFilename );
  3232.     if( NULL == lpBm )
  3233.     {
  3234.         delete lpView;
  3235.         return NULL;
  3236.     }
  3237.  
  3238.     lpView->m_lpBitmap = lpBm ;
  3239.  
  3240.     return lpView;
  3241. }
  3242.  
  3243.  
  3244.  
  3245.  
  3246. //-----------------------------------------------------------------------------
  3247. // Name: DidcvBitmapView()
  3248. // Desc: constructor
  3249. //-----------------------------------------------------------------------------
  3250. DidcvBitmapView::DidcvBitmapView()
  3251.     : DidcvView(),
  3252.       m_lpBitmap( NULL )
  3253. { }
  3254.  
  3255.  
  3256.  
  3257.  
  3258. //-----------------------------------------------------------------------------
  3259. // Name: ~DidcvBitmapView()
  3260. // Desc: Destructor
  3261. //-----------------------------------------------------------------------------
  3262. DidcvBitmapView::~DidcvBitmapView()
  3263. {
  3264.     SAFE_DELETE( m_lpBitmap );
  3265. }
  3266.  
  3267.  
  3268.  
  3269.  
  3270. //-----------------------------------------------------------------------------
  3271. // Name: GetViewSize()
  3272. // Desc: returns the size of the view image
  3273. //-----------------------------------------------------------------------------
  3274. BOOL DidcvBitmapView::GetViewSize( SIZE* lpSize ) const
  3275. {
  3276.     if( NULL == lpSize )
  3277.         return FALSE;
  3278.  
  3279.     if( NULL == m_lpBitmap )
  3280.     {
  3281.         lpSize->cx = 0;
  3282.         lpSize->cy = 0;
  3283.  
  3284.         return FALSE;
  3285.     }
  3286.  
  3287.     return m_lpBitmap->GetSize( lpSize );
  3288. }
  3289.  
  3290.  
  3291.  
  3292.  
  3293. //-----------------------------------------------------------------------------
  3294. // Name: Render()
  3295. // Desc: renders the view to a HDC
  3296. //-----------------------------------------------------------------------------
  3297. void DidcvBitmapView::Render( HDC hdc, VOID* lpBits, INT width, INT height, 
  3298.                               const POINT* ptOrigin )
  3299. {
  3300.     BOOL res = FALSE;
  3301.  
  3302.     // nothing to draw
  3303.     if( NULL == m_lpBitmap )
  3304.         return;
  3305.  
  3306.     // alpha blend by hand
  3307.     if( lpBits )
  3308.         res = m_lpBitmap->Blend( lpBits, ptOrigin->x, ptOrigin->y, width, height );
  3309.  
  3310.     if( !res )
  3311.     {
  3312.         // try alpha blending with hDC
  3313.         res = m_lpBitmap->Blend( hdc, 0, 0 );
  3314.  
  3315.         if( !res )
  3316.             // no alpha blending available - just draw
  3317.             m_lpBitmap->Draw( hdc, 0 , 0 );
  3318.     }
  3319. }
  3320.  
  3321.  
  3322.  
  3323.  
  3324. //-----------------------------------------------------------------------------
  3325. // Name: DidcvCustomView()
  3326. // Desc: constructor
  3327. //-----------------------------------------------------------------------------
  3328. DidcvCustomView::DidcvCustomView( const DidcvCustomViewInfo* lpInfo, 
  3329.                                   DWORD dwStartIndex, DWORD dwEndIndex )
  3330.     : m_lpCustomViewInfoRef( lpInfo ),
  3331.       m_dwStartIndex( dwStartIndex ),
  3332.       m_dwEndIndex( dwEndIndex )
  3333. { }
  3334.  
  3335.  
  3336.  
  3337.  
  3338. //-----------------------------------------------------------------------------
  3339. // Name: GetViewSize()
  3340. // Desc: retrieves the size of the view
  3341. //-----------------------------------------------------------------------------
  3342. BOOL DidcvCustomView::GetViewSize( SIZE* lpSize ) const
  3343. {
  3344.     if( NULL == lpSize )
  3345.         return FALSE;
  3346.  
  3347.     lpSize->cx = DIDCV_CUSTOM_VIEW_WIDTH;
  3348.     lpSize->cy = DIDCV_CUSTOM_VIEW_HEIGHT;
  3349.  
  3350.     return TRUE;
  3351. }
  3352.  
  3353.  
  3354.  
  3355. #define DIDCV_CUSTOM_BORDER_WIDTH       8
  3356. #define DIDCV_CUSTOM_BOX_WIDTH          90
  3357. #define DIDCV_CUSTOM_BOX_CONTROL_WIDTH  70
  3358. #define DIDCV_CUSTOM_BOX_HEIGHT         24
  3359. #define DIDCV_CUSTOM_LINE_BORDER        8
  3360. #define DIDCV_CUSTOM_LINE_BOX_WIDTH     32
  3361. #define DIDCV_CUSTOM_VIEWS_PER_COL     ( ( DIDCV_CUSTOM_VIEW_HEIGHT -( 2 * DIDCV_CUSTOM_BORDER_WIDTH ) ) / DIDCV_CUSTOM_BOX_HEIGHT )
  3362. //-----------------------------------------------------------------------------
  3363. // Name: Render()
  3364. // Desc: draws the custom view
  3365. //-----------------------------------------------------------------------------
  3366. VOID DidcvCustomView::Render( HDC hdc, VOID* lpBits, INT width, INT height, 
  3367.                               const POINT* pptOrigin )
  3368. {
  3369.     TCHAR tszBuffer[MAX_PATH];
  3370.     DWORD dwTextFlags = DT_WORDBREAK | DT_NOPREFIX | DT_END_ELLIPSIS 
  3371.                       | DT_EDITCONTROL | DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
  3372.     RECT rect;
  3373.     DWORD i;
  3374.  
  3375.     if( NULL == m_lpCustomViewInfoRef )
  3376.         return;
  3377.  
  3378.     for( i = m_dwStartIndex; i <= m_dwEndIndex; i++ )
  3379.     {
  3380.         // calculate coordinates based on the index
  3381.         CalcCoordinates( i, &rect );
  3382.         // copy the callout name into the buffer
  3383.         _tcscpy( tszBuffer, m_lpCustomViewInfoRef->rgObjData[i]->tszName );
  3384.         // draw the text
  3385.         DrawText( hdc, tszBuffer, -1,( LPRECT ) &rect, dwTextFlags );
  3386.     }
  3387. }
  3388.  
  3389.  
  3390.  
  3391.  
  3392. //-----------------------------------------------------------------------------
  3393. // Name: CalcCoordinates()
  3394. // Desc: calculate coordinates for control string
  3395. //-----------------------------------------------------------------------------
  3396. void DidcvCustomView::CalcCoordinates( DWORD dwIndex, LPRECT lpRect )
  3397. {
  3398.     POINT ptStart;
  3399.  
  3400.     // mod the index
  3401.     dwIndex = dwIndex % ( DIDCV_CUSTOM_VIEWS_PER_COL* 2 );
  3402.  
  3403.     // start at the top left
  3404.     ptStart.x = DIDCV_CUSTOM_BORDER_WIDTH;
  3405.     if( dwIndex >= DIDCV_CUSTOM_VIEWS_PER_COL )
  3406.     {
  3407.         // shift into the right column
  3408.         ptStart.x += DIDCV_CUSTOM_VIEW_WIDTH / 2;
  3409.         dwIndex -= DIDCV_CUSTOM_VIEWS_PER_COL;
  3410.     }
  3411.     ptStart.y = DIDCV_CUSTOM_BORDER_WIDTH + ( dwIndex* DIDCV_CUSTOM_BOX_HEIGHT );
  3412.  
  3413.     // set the coordinate
  3414.     lpRect->left = ptStart.x;
  3415.     lpRect->top = ptStart.y;
  3416.     lpRect->right = lpRect->left + DIDCV_CUSTOM_BOX_CONTROL_WIDTH;
  3417.     lpRect->bottom = lpRect->top + DIDCV_CUSTOM_BOX_HEIGHT;
  3418. }
  3419.  
  3420.  
  3421.  
  3422.  
  3423. //-----------------------------------------------------------------------------
  3424. // Name: Create()
  3425. // Desc: static function to instantiate a view
  3426. //-----------------------------------------------------------------------------
  3427. DidcvCustomView* DidcvCustomView::Create( const DidcvCustomViewInfo* lpInfo, 
  3428.                                           DWORD dwStartIndex, DWORD* lpFinishIndex )
  3429. {
  3430.     DWORD dwIndex;
  3431.  
  3432.     if( dwStartIndex >= lpInfo->dwSize )
  3433.         return NULL;
  3434.  
  3435.     // calculate how many can fit
  3436.     dwIndex = DIDCV_CUSTOM_VIEWS_PER_COL;
  3437.     dwIndex *= 2;
  3438.     dwIndex += dwStartIndex;
  3439.     dwIndex --;
  3440.     
  3441.     if( dwIndex >= lpInfo->dwSize )
  3442.         dwIndex = lpInfo->dwSize - 1;
  3443.  
  3444.     if( lpFinishIndex )
  3445.         *lpFinishIndex = dwIndex;
  3446.  
  3447.     return new DidcvCustomView( lpInfo, dwStartIndex, dwIndex );
  3448. }
  3449.  
  3450.  
  3451.  
  3452.  
  3453. //-----------------------------------------------------------------------------
  3454. // Name: CalcNumViews()
  3455. // Desc: calculates the number of views from a total count of controls
  3456. //-----------------------------------------------------------------------------
  3457. DWORD DidcvCustomView::CalcNumViews( DWORD dwCount )
  3458. {
  3459.     DWORD dwIndex;
  3460.     DWORD result;
  3461.  
  3462.     dwIndex = DIDCV_CUSTOM_VIEWS_PER_COL;
  3463.     dwIndex *= 2;
  3464.  
  3465.     result = dwCount / dwIndex +( dwCount % dwIndex ? 1 : 0 );
  3466.  
  3467.     return result;
  3468. }
  3469.  
  3470.  
  3471.  
  3472.  
  3473. //-----------------------------------------------------------------------------
  3474. // Name: CalcImageInfo()
  3475. // Desc: calculates the image info for a custom control
  3476. //-----------------------------------------------------------------------------
  3477. BOOL DidcvCustomView::CalcImageInfo( DWORD index, LPRECT rcOverlay, 
  3478.                                      LPDWORD dwNumPoints, LPPOINT rgptCalloutLine, 
  3479.                                      LPRECT rcCalloutRect )
  3480. {
  3481.     POINT ptStart;
  3482.  
  3483.     // mod the index
  3484.     index = index %( DIDCV_CUSTOM_VIEWS_PER_COL* 2 );
  3485.  
  3486.     ptStart.x = DIDCV_CUSTOM_BORDER_WIDTH + DIDCV_CUSTOM_BOX_CONTROL_WIDTH;
  3487.     if( index >= DIDCV_CUSTOM_VIEWS_PER_COL )
  3488.     {
  3489.         ptStart.x += DIDCV_CUSTOM_VIEW_WIDTH / 2;
  3490.         index -= DIDCV_CUSTOM_VIEWS_PER_COL;
  3491.     }
  3492.     ptStart.y = DIDCV_CUSTOM_BORDER_WIDTH +( index * DIDCV_CUSTOM_BOX_HEIGHT );
  3493.  
  3494.     // do nothing with the overlay rect at this point
  3495.     ZeroMemory( rcOverlay, sizeof( RECT ) );
  3496.     
  3497.     *dwNumPoints = 2;
  3498.     rgptCalloutLine[1].x = ptStart.x + DIDCV_CUSTOM_LINE_BORDER;
  3499.     rgptCalloutLine[1].y = ptStart.y +( DIDCV_CUSTOM_BOX_HEIGHT / 2 );
  3500.     rgptCalloutLine[0].x = rgptCalloutLine[1].x + DIDCV_CUSTOM_LINE_BOX_WIDTH - 
  3501.                            2 * DIDCV_CUSTOM_LINE_BORDER;
  3502.     rgptCalloutLine[0].y = rgptCalloutLine[1].y;
  3503.     
  3504.     rcCalloutRect->left = ptStart.x + DIDCV_CUSTOM_LINE_BOX_WIDTH;
  3505.     rcCalloutRect->top = ptStart.y;
  3506.     rcCalloutRect->right = rcCalloutRect->left + DIDCV_CUSTOM_BOX_WIDTH;
  3507.     rcCalloutRect->bottom = rcCalloutRect->top + DIDCV_CUSTOM_BOX_HEIGHT;
  3508.  
  3509.     return TRUE;
  3510. }
  3511.  
  3512.  
  3513.  
  3514.  
  3515. //-----------------------------------------------------------------------------
  3516. // Name: DidcvViewManager()
  3517. // Desc: constructor
  3518. //-----------------------------------------------------------------------------
  3519. DidcvViewManager::DidcvViewManager()
  3520.     : m_ppViewTable( NULL ),
  3521.       m_capacity( 0 ),
  3522.       m_size( 0 )
  3523. {
  3524.     // initialized
  3525. }
  3526.  
  3527.  
  3528.  
  3529.  
  3530. //-----------------------------------------------------------------------------
  3531. // Name: ~DidcvViewManager()
  3532. // Desc: destructor
  3533. //-----------------------------------------------------------------------------
  3534. DidcvViewManager::~DidcvViewManager()
  3535. {
  3536.     CleanUp();
  3537. }
  3538.  
  3539.  
  3540.  
  3541.  
  3542. //-----------------------------------------------------------------------------
  3543. // Name: SetSize()
  3544. // Desc: sets the capacity of the view manager
  3545. //-----------------------------------------------------------------------------
  3546. BOOL DidcvViewManager::SetCapacity( UINT uCapacity, BOOL bDeleteContent )
  3547. {
  3548.     if( m_ppViewTable )
  3549.     {
  3550.         if( bDeleteContent )
  3551.             CleanUp();
  3552.         else
  3553.             free( m_ppViewTable );
  3554.     }
  3555.  
  3556.     m_capacity = uCapacity;
  3557.     m_size = 0;
  3558.     m_ppViewTable =( DidcvView ** ) malloc( uCapacity * sizeof( DidcvView* ) );
  3559.  
  3560.     if( NULL == m_ppViewTable )
  3561.     {
  3562.         m_capacity = 0;
  3563.         return FALSE;
  3564.     }
  3565.  
  3566.     return TRUE;
  3567. }
  3568.  
  3569.  
  3570.  
  3571.  
  3572. //-----------------------------------------------------------------------------
  3573. // Name: CleanUp()
  3574. // Desc: frees the table and the contents of the table
  3575. //-----------------------------------------------------------------------------
  3576. void DidcvViewManager::CleanUp()
  3577. {
  3578.     UINT i;
  3579.  
  3580.     if( m_ppViewTable )
  3581.     {
  3582.         // free the entries
  3583.         for( i = 0; i < m_size ; i++ )
  3584.             if( m_ppViewTable [i] )
  3585.                 delete m_ppViewTable [i];
  3586.  
  3587.         // free the table
  3588.         free( m_ppViewTable );
  3589.         m_ppViewTable = NULL;
  3590.     }
  3591. }
  3592.  
  3593.  
  3594.  
  3595.  
  3596. //-----------------------------------------------------------------------------
  3597. // Name: AddImage()
  3598. // Desc: adds a DidcvView to the to be stored and managed
  3599. //-----------------------------------------------------------------------------
  3600. BOOL DidcvViewManager::AddImage( DidcvView* lpView, INT nOffset )
  3601. {
  3602.     // save the offset value in the View object
  3603.     lpView->SetOffset( nOffset );
  3604.  
  3605.     // try to allocate the first free entry
  3606.     if( m_size >= m_capacity )
  3607.     {
  3608.         lpView->SetID( DIDCV_INVALID_ID );
  3609.         return FALSE;
  3610.     }
  3611.  
  3612.     m_ppViewTable [m_size] = lpView;
  3613.  
  3614.     // save the table entry as the unique view id
  3615.     lpView->SetID( ( INT )m_size );
  3616.  
  3617.     m_size ++;
  3618.  
  3619.     return TRUE;
  3620. }
  3621.  
  3622.  
  3623.  
  3624.  
  3625. //-----------------------------------------------------------------------------
  3626. // Name: GetImage()
  3627. // Desc: returns the DidcvView for a given internal identifier
  3628. //-----------------------------------------------------------------------------
  3629. DidcvView* DidcvViewManager::GetImage( INT nID )
  3630. {
  3631.     // make sure is within bounds
  3632.     if( nID < 0 ||( UINT ) nID >= m_capacity )
  3633.         return NULL;
  3634.  
  3635.     // return the view object in the table
  3636.     return m_ppViewTable[ nID ];
  3637. }
  3638.  
  3639.  
  3640.  
  3641.  
  3642. //-----------------------------------------------------------------------------
  3643. // Name: GetImageByOffset()
  3644. // Desc: returns the DidcvView for a given offset from the original GetImage
  3645. //       image info array
  3646. //-----------------------------------------------------------------------------
  3647. DidcvView* DidcvViewManager::GetImageByOffset( INT nOffset )
  3648. {
  3649.     DWORD i;
  3650.     if( nOffset < 0 )
  3651.         return NULL;
  3652.  
  3653.     // look for the offset in the entry
  3654.     for( i = 0; i < m_size; i++ )
  3655.         if( m_ppViewTable[i] &&( m_ppViewTable[i]->GetOffset() == nOffset ) )
  3656.             return m_ppViewTable[i];
  3657.  
  3658.     return NULL;
  3659. }
  3660.  
  3661.  
  3662.  
  3663.  
  3664. //-----------------------------------------------------------------------------
  3665. // Name: GetNumViews()
  3666. // Desc: returns the number of images currently stored in the view manager
  3667. //-----------------------------------------------------------------------------
  3668. UINT DidcvViewManager::GetNumViews() const
  3669. {
  3670.     return m_size;
  3671. }
  3672.  
  3673.  
  3674.  
  3675.  
  3676. //-----------------------------------------------------------------------------
  3677. // Name: DidcvDirect3DSurface8Clone
  3678. // Desc: a clone surface
  3679. //-----------------------------------------------------------------------------
  3680. class DidcvDirect3DSurface8Clone : public IUnknown
  3681. {
  3682. private:
  3683.     int m_iRefCount;
  3684.     BYTE *m_pData;
  3685.     D3DSURFACE_DESC m_Desc;
  3686.  
  3687. public:
  3688.     DidcvDirect3DSurface8Clone() : m_pData( NULL ), m_iRefCount( 1 ) { }
  3689.     ~DidcvDirect3DSurface8Clone() { delete[] m_pData; }
  3690.  
  3691. public:     
  3692.     // IUnknown methods
  3693.     STDMETHOD( QueryInterface )( REFIID  riid, VOID  **ppvObj ) { return E_NOINTERFACE; }
  3694.     STDMETHOD_( ULONG,AddRef )() { return ++m_iRefCount; }
  3695.     STDMETHOD_( ULONG,Release )()
  3696.     {
  3697.         if( !--m_iRefCount )
  3698.         {
  3699.             delete this;
  3700.             return 0;
  3701.         }
  3702.         return m_iRefCount;
  3703.     }
  3704.  
  3705.     // IBuffer methods
  3706.     STDMETHOD( SetPrivateData )( REFGUID riid, CONST VOID *pvData, DWORD cbData, DWORD   dwFlags ) { return S_OK; }
  3707.     STDMETHOD( GetPrivateData )( REFGUID riid, VOID* pvData, DWORD  *pcbData ) { return S_OK; }
  3708.     STDMETHOD( FreePrivateData )( REFGUID riid ) { return S_OK; }
  3709.     STDMETHOD( GetContainer )( REFIID riid, void **ppContainer ) { return S_OK; }
  3710.     STDMETHOD( GetDevice )( IDirect3DDevice8 **ppDevice ) { return S_OK; }
  3711.  
  3712.     // IDirect3DSurface8 methods
  3713.     STDMETHOD_( D3DSURFACE_DESC, GetDesc )() { return m_Desc; }
  3714.     STDMETHOD( LockRect )( D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD dwFlags )
  3715.     {
  3716.         // Assume the entire surface is being locked.
  3717.         pLockedRect->Pitch = m_Desc.Width * 4;
  3718.         pLockedRect->pBits = m_pData;
  3719.         return S_OK;
  3720.     }
  3721.     STDMETHOD( UnlockRect )() { return S_OK; }
  3722.     BOOL Create( int iWidth, int iHeight )
  3723.     {
  3724.         m_pData = new BYTE[iWidth * iHeight * 4];
  3725.         if( !m_pData ) return FALSE;
  3726.  
  3727.         m_Desc.Format = D3DFMT_A8R8G8B8;
  3728.         m_Desc.Type = D3DRTYPE_SURFACE;
  3729.         m_Desc.Usage = 0;
  3730.         m_Desc.Pool = D3DPOOL_SYSTEMMEM;
  3731.         m_Desc.Size = iWidth * iHeight * 4;
  3732.         m_Desc.MultiSampleType = D3DMULTISAMPLE_NONE;
  3733.         m_Desc.Width = iWidth;
  3734.         m_Desc.Height = iHeight;
  3735.         return TRUE;
  3736.     }
  3737. };
  3738.  
  3739.  
  3740.  
  3741.  
  3742. //-----------------------------------------------------------------------------
  3743. // Name: GetCloneSurface()
  3744. // Desc: 
  3745. //-----------------------------------------------------------------------------
  3746. IDirect3DSurface8* GetCloneSurface( int iWidth, int iHeight )
  3747. {
  3748.     DidcvDirect3DSurface8Clone *pSurf = new DidcvDirect3DSurface8Clone;
  3749.  
  3750.     if( !pSurf ) return NULL;
  3751.     if( !pSurf->Create( iWidth, iHeight ) )
  3752.     {
  3753.         delete pSurf;
  3754.         return NULL;
  3755.     }
  3756.  
  3757.     return( IDirect3DSurface8* )pSurf;
  3758. }
  3759.  
  3760.  
  3761.  
  3762.  
  3763. //-----------------------------------------------------------------------------
  3764. // Name: CreateViaD3Dx()
  3765. // Desc: loads a bitmap from .BMP or .PNG using D3Dx
  3766. //-----------------------------------------------------------------------------
  3767. DidcvBitmap* DidcvBitmap::CreateViaD3dx( LPCTSTR tszFileName )
  3768. {
  3769.     LPDIRECT3DSURFACE8 lpSurf = NULL;
  3770.     HRESULT hr;
  3771.     D3DXIMAGE_INFO d3dxImgInfo;
  3772.     DidcvBitmap* pbm = NULL;
  3773.     BYTE* pbData = NULL;
  3774.     UINT y, i;
  3775.     UINT width, height, pitch;
  3776.  
  3777.     lpSurf = GetCloneSurface( DIDCV_MAX_IMAGE_WIDTH, DIDCV_MAX_IMAGE_HEIGHT );
  3778.     if( lpSurf )
  3779.     {
  3780.         if( FAILED( D3DXLoadSurfaceFromFile( lpSurf, NULL, NULL, tszFileName, 
  3781.                                 NULL, D3DX_FILTER_NONE, 0, &d3dxImgInfo ) ) )
  3782.             goto label_release;
  3783.     }
  3784.  
  3785.     width = d3dxImgInfo.Width;
  3786.     height = d3dxImgInfo.Height;
  3787.     pitch = width * 4;
  3788.  
  3789.     // Create a bitmap and copy the texture content onto it.
  3790.     LPBYTE pDIBBits;
  3791.     HBITMAP hDIB;
  3792.     BITMAPINFO bmi;
  3793.     bmi.bmiHeader.biSize = sizeof( bmi.bmiHeader );
  3794.     bmi.bmiHeader.biWidth = width;
  3795.     bmi.bmiHeader.biHeight = height;
  3796.     bmi.bmiHeader.biPlanes = 1;
  3797.     bmi.bmiHeader.biBitCount = 32;
  3798.     bmi.bmiHeader.biCompression = BI_RGB;
  3799.     bmi.bmiHeader.biSizeImage = 0;
  3800.     bmi.bmiHeader.biXPelsPerMeter = 0;
  3801.     bmi.bmiHeader.biYPelsPerMeter = 0;
  3802.     bmi.bmiHeader.biClrUsed = 0;
  3803.     bmi.bmiHeader.biClrImportant = 0;
  3804.     hDIB = CreateDIBSection( NULL, &bmi, DIB_RGB_COLORS,( LPVOID* )&pDIBBits, NULL, 0 );
  3805.     if( !hDIB )
  3806.          goto label_release;
  3807.  
  3808.     // Lock the surface
  3809.     D3DLOCKED_RECT D3DRect;
  3810.     hr = lpSurf->LockRect( &D3DRect, NULL, 0 );
  3811.     if( FAILED( hr ) )
  3812.          goto label_release;
  3813.     
  3814.     // Copy the bits
  3815.     // Note that the image is reversed in Y direction, so we need to re-reverse it.
  3816.     for( y = 0; y < height; ++y )
  3817.         CopyMemory( pDIBBits +( y * pitch ),( LPBYTE ) D3DRect.pBits + 
  3818.                     ( ( height - y ) * D3DRect.Pitch ), width * 4 );  // 512 pixels per line, 32 bits per pixel
  3819.  
  3820.     // process the pixel data based on alpha for blending
  3821.     pbData =( LPBYTE ) pDIBBits;
  3822.     for( i = 0; i < width * height; ++i )
  3823.     {
  3824.         BYTE bAlpha = pbData[i * 4 + 3];
  3825.         pbData[i * 4] = pbData[i * 4] * bAlpha / 255;
  3826.         pbData[i * 4 + 1] = pbData[i * 4 + 1] * bAlpha / 255;
  3827.         pbData[i * 4 + 2] = pbData[i * 4 + 2] * bAlpha / 255;
  3828.     }
  3829.  
  3830.     // Unlock
  3831.     lpSurf->UnlockRect();
  3832.  
  3833.     pbm = new DidcvBitmap;
  3834.     if( NULL == pbm )
  3835.         goto label_release;
  3836.  
  3837.     pbm->m_hbitmap = hDIB;
  3838.     pbm->m_lpBits = pDIBBits;
  3839.     pbm->FigureSize();
  3840.  
  3841.  
  3842. label_release:
  3843.  
  3844.     if( lpSurf ) lpSurf->Release();
  3845.     if( !pbm && hDIB )
  3846.         DeleteObject( hDIB );
  3847.  
  3848.     return pbm;
  3849. }
  3850.